2008-10-24 05:07:24 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
2013-02-18 08:19:28 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SECTION:compositor
|
|
|
|
* @Title: MetaCompositor
|
|
|
|
* @Short_Description: Compositor API
|
2013-03-15 06:28:53 -04:00
|
|
|
*
|
|
|
|
* At a high-level, a window is not-visible or visible. When a
|
|
|
|
* window is added (with meta_compositor_add_window()) it is not visible.
|
|
|
|
* meta_compositor_show_window() indicates a transition from not-visible to
|
|
|
|
* visible. Some of the reasons for this:
|
|
|
|
*
|
|
|
|
* - Window newly created
|
|
|
|
* - Window is unminimized
|
|
|
|
* - Window is moved to the current desktop
|
|
|
|
* - Window was made sticky
|
|
|
|
*
|
|
|
|
* meta_compositor_hide_window() indicates that the window has transitioned from
|
|
|
|
* visible to not-visible. Some reasons include:
|
|
|
|
*
|
|
|
|
* - Window was destroyed
|
|
|
|
* - Window is minimized
|
|
|
|
* - Window is moved to a different desktop
|
|
|
|
* - Window no longer sticky.
|
|
|
|
*
|
|
|
|
* Note that combinations are possible - a window might have first
|
|
|
|
* been minimized and then moved to a different desktop. The 'effect' parameter
|
|
|
|
* to meta_compositor_show_window() and meta_compositor_hide_window() is a hint
|
|
|
|
* as to the appropriate effect to show the user and should not
|
|
|
|
* be considered to be indicative of a state change.
|
|
|
|
*
|
|
|
|
* When the active workspace is changed, meta_compositor_switch_workspace() is
|
|
|
|
* called first, then meta_compositor_show_window() and
|
|
|
|
* meta_compositor_hide_window() are called individually for each window
|
|
|
|
* affected, with an effect of META_COMP_EFFECT_NONE.
|
|
|
|
* If hiding windows will affect the switch workspace animation, the
|
|
|
|
* compositor needs to delay hiding the windows until the switch
|
|
|
|
* workspace animation completes.
|
|
|
|
*
|
2013-03-15 06:29:19 -04:00
|
|
|
* # Containers #
|
|
|
|
*
|
2013-05-22 12:24:00 -04:00
|
|
|
* There's two containers in the stage that are used to place window actors, here
|
2013-03-15 06:29:19 -04:00
|
|
|
* are listed in the order in which they are painted:
|
|
|
|
*
|
2017-08-26 15:43:17 -04:00
|
|
|
* - window group, accessible with meta_get_window_group_for_display()
|
|
|
|
* - top window group, accessible with meta_get_top_window_group_for_display()
|
2013-03-15 06:29:19 -04:00
|
|
|
*
|
|
|
|
* Mutter will place actors representing windows in the window group, except for
|
|
|
|
* override-redirect windows (ie. popups and menus) which will be placed in the
|
2013-05-22 12:24:00 -04:00
|
|
|
* top window group.
|
2013-02-18 08:19:28 -05:00
|
|
|
*/
|
2008-10-24 05:07:24 -04:00
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "config.h"
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "compositor/compositor-private.h"
|
2008-06-04 08:58:36 -04:00
|
|
|
|
|
|
|
#include <X11/extensions/Xcomposite.h>
|
2008-10-24 05:07:24 -04:00
|
|
|
|
2019-03-22 08:53:00 -04:00
|
|
|
#include "backends/x11/meta-backend-x11.h"
|
|
|
|
#include "backends/x11/meta-event-x11.h"
|
|
|
|
#include "backends/x11/meta-stage-x11.h"
|
2016-05-25 02:40:12 -04:00
|
|
|
#include "clutter/clutter-mutter.h"
|
2020-02-17 12:32:35 -05:00
|
|
|
#include "cogl/cogl.h"
|
2020-03-03 03:32:33 -05:00
|
|
|
#include "compositor/meta-later-private.h"
|
2018-12-22 09:21:34 -05:00
|
|
|
#include "compositor/meta-window-actor-x11.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "compositor/meta-window-actor-private.h"
|
|
|
|
#include "compositor/meta-window-group-private.h"
|
|
|
|
#include "core/frame.h"
|
|
|
|
#include "core/util-private.h"
|
|
|
|
#include "core/window-private.h"
|
|
|
|
#include "meta/compositor-mutter.h"
|
|
|
|
#include "meta/main.h"
|
|
|
|
#include "meta/meta-backend.h"
|
|
|
|
#include "meta/meta-background-actor.h"
|
|
|
|
#include "meta/meta-background-group.h"
|
2021-04-19 10:13:47 -04:00
|
|
|
#include "meta/meta-context.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "meta/meta-shadow-factory.h"
|
|
|
|
#include "meta/meta-x11-errors.h"
|
|
|
|
#include "meta/prefs.h"
|
|
|
|
#include "meta/window.h"
|
2017-08-26 12:26:30 -04:00
|
|
|
#include "x11/meta-x11-display-private.h"
|
|
|
|
|
2014-08-27 12:41:26 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
2020-04-23 05:14:05 -04:00
|
|
|
#include "compositor/meta-window-actor-wayland.h"
|
2014-03-18 22:01:31 -04:00
|
|
|
#include "wayland/meta-wayland-private.h"
|
2014-08-27 12:41:26 -04:00
|
|
|
#endif
|
2014-03-18 22:01:31 -04:00
|
|
|
|
2019-08-19 04:24:17 -04:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
|
|
|
|
PROP_DISPLAY,
|
2020-04-16 13:14:21 -04:00
|
|
|
PROP_BACKEND,
|
2019-08-19 04:24:17 -04:00
|
|
|
|
|
|
|
N_PROPS
|
|
|
|
};
|
|
|
|
|
|
|
|
static GParamSpec *obj_props[N_PROPS] = { NULL, };
|
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
typedef struct _MetaCompositorPrivate
|
|
|
|
{
|
|
|
|
GObject parent;
|
|
|
|
|
|
|
|
MetaDisplay *display;
|
2020-04-16 13:14:21 -04:00
|
|
|
MetaBackend *backend;
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
gulong stage_presented_id;
|
2020-05-29 18:02:42 -04:00
|
|
|
gulong before_paint_handler_id;
|
|
|
|
gulong after_paint_handler_id;
|
2022-05-12 11:42:20 -04:00
|
|
|
gulong window_visibility_updated_id;
|
2022-07-10 07:44:34 -04:00
|
|
|
gulong monitors_changed_internal_id;
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
int64_t server_time_query_time;
|
|
|
|
int64_t server_time_offset;
|
|
|
|
|
|
|
|
gboolean server_time_is_monotonic_time;
|
|
|
|
|
|
|
|
ClutterActor *window_group;
|
|
|
|
ClutterActor *top_window_group;
|
|
|
|
ClutterActor *feedback_group;
|
|
|
|
|
|
|
|
GList *windows;
|
|
|
|
|
|
|
|
CoglContext *context;
|
|
|
|
|
2022-07-02 15:51:13 -04:00
|
|
|
gboolean needs_update_top_window_actors;
|
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaWindowActor *top_window_actor;
|
|
|
|
gulong top_window_actor_destroy_id;
|
|
|
|
|
|
|
|
int disable_unredirect_count;
|
|
|
|
|
|
|
|
int switch_workspace_in_progress;
|
|
|
|
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
gboolean frame_in_progress;
|
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaPluginManager *plugin_mgr;
|
2020-03-03 03:32:33 -05:00
|
|
|
|
|
|
|
MetaLaters *laters;
|
2019-08-14 13:04:41 -04:00
|
|
|
} MetaCompositorPrivate;
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCompositor, meta_compositor,
|
|
|
|
G_TYPE_OBJECT)
|
2019-01-11 11:18:27 -05:00
|
|
|
|
2022-07-10 07:44:34 -04:00
|
|
|
static GQuark quark_compositor_view;
|
|
|
|
|
2016-06-08 01:07:09 -04:00
|
|
|
static void
|
|
|
|
on_presented (ClutterStage *stage,
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
ClutterStageView *stage_view,
|
2016-06-08 01:07:09 -04:00
|
|
|
ClutterFrameInfo *frame_info,
|
|
|
|
MetaCompositor *compositor);
|
|
|
|
|
2019-04-29 15:57:03 -04:00
|
|
|
static void
|
|
|
|
on_top_window_actor_destroyed (MetaWindowActor *window_actor,
|
|
|
|
MetaCompositor *compositor);
|
|
|
|
|
2014-03-18 17:31:22 -04:00
|
|
|
static void sync_actor_stacking (MetaCompositor *compositor);
|
2009-06-26 15:33:20 -04:00
|
|
|
|
2008-06-04 08:58:36 -04:00
|
|
|
static void
|
2014-03-18 17:31:22 -04:00
|
|
|
meta_finish_workspace_switch (MetaCompositor *compositor)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2009-06-26 15:33:20 -04:00
|
|
|
GList *l;
|
2008-06-04 08:58:36 -04:00
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
/* Finish hiding and showing actors for the new workspace */
|
2019-08-14 13:04:41 -04:00
|
|
|
for (l = priv->windows; l; l = l->next)
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_window_actor_sync_visibility (l->data);
|
2008-06-06 09:17:38 -04:00
|
|
|
|
2014-03-18 17:22:42 -04:00
|
|
|
/* Fix up stacking order. */
|
2014-03-18 17:31:22 -04:00
|
|
|
sync_actor_stacking (compositor);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
void
|
2014-03-18 17:31:22 -04:00
|
|
|
meta_switch_workspace_completed (MetaCompositor *compositor)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
/* FIXME -- must redo stacking order */
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->switch_workspace_in_progress--;
|
|
|
|
if (priv->switch_workspace_in_progress < 0)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2009-06-26 15:33:20 -04:00
|
|
|
g_warning ("Error in workspace_switch accounting!");
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->switch_workspace_in_progress = 0;
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
if (!priv->switch_workspace_in_progress)
|
2014-03-18 17:31:22 -04:00
|
|
|
meta_finish_workspace_switch (compositor);
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_destroy (MetaCompositor *compositor)
|
|
|
|
{
|
2019-01-11 11:18:27 -05:00
|
|
|
g_object_run_dispose (G_OBJECT (compositor));
|
|
|
|
g_object_unref (compositor);
|
2008-06-04 08:58:36 -04:00
|
|
|
}
|
|
|
|
|
2014-03-18 17:31:22 -04:00
|
|
|
/* compat helper */
|
|
|
|
static MetaCompositor *
|
2017-08-26 15:43:17 -04:00
|
|
|
get_compositor_for_display (MetaDisplay *display)
|
2014-03-18 17:31:22 -04:00
|
|
|
{
|
2017-08-26 15:43:17 -04:00
|
|
|
return display->compositor;
|
2014-03-18 17:31:22 -04:00
|
|
|
}
|
|
|
|
|
2010-09-01 15:39:53 -04:00
|
|
|
/**
|
2017-08-26 15:43:17 -04:00
|
|
|
* meta_get_stage_for_display:
|
|
|
|
* @display: a #MetaDisplay
|
2010-09-01 15:39:53 -04:00
|
|
|
*
|
2017-08-26 15:43:17 -04:00
|
|
|
* Returns: (transfer none): The #ClutterStage for the display
|
2010-09-01 15:39:53 -04:00
|
|
|
*/
|
2008-10-09 08:22:32 -04:00
|
|
|
ClutterActor *
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_get_stage_for_display (MetaDisplay *display)
|
2008-10-09 08:22:32 -04:00
|
|
|
{
|
2019-11-09 17:26:00 -05:00
|
|
|
MetaCompositor *compositor;
|
|
|
|
MetaCompositorPrivate *priv;
|
|
|
|
|
|
|
|
g_return_val_if_fail (display, NULL);
|
|
|
|
|
|
|
|
compositor = get_compositor_for_display (display);
|
|
|
|
g_return_val_if_fail (compositor, NULL);
|
|
|
|
priv = meta_compositor_get_instance_private (compositor);
|
2019-08-14 13:04:41 -04:00
|
|
|
|
2020-04-16 13:14:21 -04:00
|
|
|
return meta_backend_get_stage (priv->backend);
|
2008-10-09 08:22:32 -04:00
|
|
|
}
|
|
|
|
|
2010-09-01 15:39:53 -04:00
|
|
|
/**
|
2017-08-26 15:43:17 -04:00
|
|
|
* meta_get_window_group_for_display:
|
|
|
|
* @display: a #MetaDisplay
|
2010-09-01 15:39:53 -04:00
|
|
|
*
|
2017-08-26 15:43:17 -04:00
|
|
|
* Returns: (transfer none): The window group corresponding to @display
|
2010-09-01 15:39:53 -04:00
|
|
|
*/
|
2008-10-28 07:30:29 -04:00
|
|
|
ClutterActor *
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_get_window_group_for_display (MetaDisplay *display)
|
2008-10-28 07:30:29 -04:00
|
|
|
{
|
2019-11-09 17:26:00 -05:00
|
|
|
MetaCompositor *compositor;
|
|
|
|
MetaCompositorPrivate *priv;
|
|
|
|
|
|
|
|
g_return_val_if_fail (display, NULL);
|
|
|
|
|
|
|
|
compositor = get_compositor_for_display (display);
|
|
|
|
g_return_val_if_fail (compositor, NULL);
|
|
|
|
priv = meta_compositor_get_instance_private (compositor);
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
return priv->window_group;
|
2008-10-28 07:30:29 -04:00
|
|
|
}
|
|
|
|
|
2012-12-27 08:04:12 -05:00
|
|
|
/**
|
2017-08-26 15:43:17 -04:00
|
|
|
* meta_get_top_window_group_for_display:
|
|
|
|
* @display: a #MetaDisplay
|
2012-12-27 08:04:12 -05:00
|
|
|
*
|
2017-08-26 15:43:17 -04:00
|
|
|
* Returns: (transfer none): The top window group corresponding to @display
|
2012-12-27 08:04:12 -05:00
|
|
|
*/
|
|
|
|
ClutterActor *
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_get_top_window_group_for_display (MetaDisplay *display)
|
2012-12-27 08:04:12 -05:00
|
|
|
{
|
2019-11-09 17:26:00 -05:00
|
|
|
MetaCompositor *compositor;
|
|
|
|
MetaCompositorPrivate *priv;
|
|
|
|
|
|
|
|
g_return_val_if_fail (display, NULL);
|
|
|
|
|
|
|
|
compositor = get_compositor_for_display (display);
|
|
|
|
g_return_val_if_fail (compositor, NULL);
|
|
|
|
priv = meta_compositor_get_instance_private (compositor);
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
return priv->top_window_group;
|
2012-12-27 08:04:12 -05:00
|
|
|
}
|
|
|
|
|
2014-10-06 10:46:26 -04:00
|
|
|
/**
|
2017-08-26 15:43:17 -04:00
|
|
|
* meta_get_feedback_group_for_display:
|
|
|
|
* @display: a #MetaDisplay
|
2014-10-06 10:46:26 -04:00
|
|
|
*
|
2017-08-26 15:43:17 -04:00
|
|
|
* Returns: (transfer none): The feedback group corresponding to @display
|
2014-10-06 10:46:26 -04:00
|
|
|
*/
|
|
|
|
ClutterActor *
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_get_feedback_group_for_display (MetaDisplay *display)
|
2014-10-06 10:46:26 -04:00
|
|
|
{
|
2019-11-09 17:26:00 -05:00
|
|
|
MetaCompositor *compositor;
|
|
|
|
MetaCompositorPrivate *priv;
|
|
|
|
|
|
|
|
g_return_val_if_fail (display, NULL);
|
|
|
|
|
|
|
|
compositor = get_compositor_for_display (display);
|
|
|
|
g_return_val_if_fail (compositor, NULL);
|
|
|
|
priv = meta_compositor_get_instance_private (compositor);
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
return priv->feedback_group;
|
2014-10-06 10:46:26 -04:00
|
|
|
}
|
|
|
|
|
2010-09-01 15:39:53 -04:00
|
|
|
/**
|
2010-10-18 13:27:14 -04:00
|
|
|
* meta_get_window_actors:
|
2017-08-26 15:43:17 -04:00
|
|
|
* @display: a #MetaDisplay
|
2010-09-01 15:39:53 -04:00
|
|
|
*
|
2017-08-26 15:43:17 -04:00
|
|
|
* Returns: (transfer none) (element-type Clutter.Actor): The set of #MetaWindowActor on @display
|
2010-09-01 15:39:53 -04:00
|
|
|
*/
|
2008-10-24 05:07:24 -04:00
|
|
|
GList *
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_get_window_actors (MetaDisplay *display)
|
2008-10-24 05:07:24 -04:00
|
|
|
{
|
2019-11-09 17:26:00 -05:00
|
|
|
MetaCompositor *compositor;
|
|
|
|
MetaCompositorPrivate *priv;
|
|
|
|
|
|
|
|
g_return_val_if_fail (display, NULL);
|
|
|
|
|
|
|
|
compositor = get_compositor_for_display (display);
|
|
|
|
g_return_val_if_fail (compositor, NULL);
|
|
|
|
priv = meta_compositor_get_instance_private (compositor);
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
return priv->windows;
|
2008-10-24 05:07:24 -04:00
|
|
|
}
|
2008-10-09 08:22:32 -04:00
|
|
|
|
2013-05-23 16:21:24 -04:00
|
|
|
void
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_focus_stage_window (MetaDisplay *display,
|
|
|
|
guint32 timestamp)
|
2013-05-23 16:21:24 -04:00
|
|
|
{
|
|
|
|
ClutterStage *stage;
|
|
|
|
Window window;
|
|
|
|
|
2017-08-26 15:43:17 -04:00
|
|
|
stage = CLUTTER_STAGE (meta_get_stage_for_display (display));
|
2013-05-23 16:21:24 -04:00
|
|
|
if (!stage)
|
|
|
|
return;
|
|
|
|
|
2019-03-22 08:53:00 -04:00
|
|
|
window = meta_x11_get_stage_window (stage);
|
2013-05-23 16:21:24 -04:00
|
|
|
|
2014-02-23 12:28:51 -05:00
|
|
|
if (window == None)
|
|
|
|
return;
|
2013-05-23 16:21:24 -04:00
|
|
|
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_x11_display_set_input_focus_xwindow (display->x11_display,
|
2017-08-26 14:51:28 -04:00
|
|
|
window,
|
|
|
|
timestamp);
|
2013-05-23 16:21:24 -04:00
|
|
|
}
|
|
|
|
|
2013-05-24 17:58:55 -04:00
|
|
|
gboolean
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_stage_is_focused (MetaDisplay *display)
|
2013-05-24 17:58:55 -04:00
|
|
|
{
|
|
|
|
ClutterStage *stage;
|
2014-02-23 12:28:51 -05:00
|
|
|
Window window;
|
2013-05-24 17:58:55 -04:00
|
|
|
|
2014-02-23 12:29:21 -05:00
|
|
|
if (meta_is_wayland_compositor ())
|
|
|
|
return TRUE;
|
|
|
|
|
2017-08-26 15:43:17 -04:00
|
|
|
stage = CLUTTER_STAGE (meta_get_stage_for_display (display));
|
2013-05-24 17:58:55 -04:00
|
|
|
if (!stage)
|
|
|
|
return FALSE;
|
|
|
|
|
2019-03-22 08:53:00 -04:00
|
|
|
window = meta_x11_get_stage_window (stage);
|
2014-02-23 12:28:51 -05:00
|
|
|
|
|
|
|
if (window == None)
|
|
|
|
return FALSE;
|
|
|
|
|
2017-08-26 15:43:17 -04:00
|
|
|
return (display->x11_display->focus_xwindow == window);
|
2013-05-24 17:58:55 -04:00
|
|
|
}
|
|
|
|
|
2021-11-17 17:31:11 -05:00
|
|
|
void
|
2021-02-13 06:48:31 -05:00
|
|
|
meta_compositor_grab_begin (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
META_COMPOSITOR_GET_CLASS (compositor)->grab_begin (compositor);
|
|
|
|
}
|
|
|
|
|
2021-11-17 17:31:11 -05:00
|
|
|
void
|
2021-02-13 06:48:31 -05:00
|
|
|
meta_compositor_grab_end (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
META_COMPOSITOR_GET_CLASS (compositor)->grab_end (compositor);
|
|
|
|
}
|
|
|
|
|
2013-03-01 14:41:11 -05:00
|
|
|
static void
|
2017-08-26 16:24:21 -04:00
|
|
|
redirect_windows (MetaX11Display *x11_display)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2021-04-19 10:13:47 -04:00
|
|
|
MetaBackend *backend = meta_get_backend ();
|
|
|
|
MetaContext *context = meta_backend_get_context (backend);
|
2017-08-26 12:26:30 -04:00
|
|
|
Display *xdisplay = meta_x11_display_get_xdisplay (x11_display);
|
|
|
|
Window xroot = meta_x11_display_get_xroot (x11_display);
|
|
|
|
int screen_number = meta_x11_display_get_screen_number (x11_display);
|
|
|
|
guint n_retries;
|
|
|
|
guint max_retries;
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2021-04-19 10:13:47 -04:00
|
|
|
if (meta_context_is_replacing (context))
|
2011-06-21 14:05:59 -04:00
|
|
|
max_retries = 5;
|
|
|
|
else
|
|
|
|
max_retries = 1;
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2011-06-21 14:05:59 -04:00
|
|
|
n_retries = 0;
|
|
|
|
|
2011-06-30 15:23:41 -04:00
|
|
|
/* Some compositors (like old versions of Mutter) might not properly unredirect
|
|
|
|
* subwindows before destroying the WM selection window; so we wait a while
|
|
|
|
* for such a compositor to exit before giving up.
|
2011-06-21 14:05:59 -04:00
|
|
|
*/
|
|
|
|
while (TRUE)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2017-08-27 14:48:55 -04:00
|
|
|
meta_x11_error_trap_push (x11_display);
|
2011-06-21 14:05:59 -04:00
|
|
|
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
|
|
|
XSync (xdisplay, FALSE);
|
|
|
|
|
2017-08-27 14:48:55 -04:00
|
|
|
if (!meta_x11_error_trap_pop_with_return (x11_display))
|
2011-06-21 14:05:59 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (n_retries == max_retries)
|
2011-06-30 15:23:41 -04:00
|
|
|
{
|
|
|
|
/* This probably means that a non-WM compositor like xcompmgr is running;
|
|
|
|
* we have no way to get it to exit */
|
2016-09-29 18:56:23 -04:00
|
|
|
meta_fatal (_("Another compositing manager is already running on screen %i on display “%s”."),
|
2017-08-26 12:26:30 -04:00
|
|
|
screen_number, x11_display->name);
|
2011-06-30 15:23:41 -04:00
|
|
|
}
|
2011-06-21 14:05:59 -04:00
|
|
|
|
|
|
|
n_retries++;
|
|
|
|
g_usleep (G_USEC_PER_SEC);
|
2008-06-04 08:58:36 -04:00
|
|
|
}
|
2013-03-01 14:41:11 -05:00
|
|
|
}
|
|
|
|
|
2019-05-24 15:04:56 -04:00
|
|
|
void
|
|
|
|
meta_compositor_redirect_x11_windows (MetaCompositor *compositor)
|
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
MetaDisplay *display = priv->display;
|
2019-05-24 15:04:56 -04:00
|
|
|
|
|
|
|
if (display->x11_display)
|
|
|
|
redirect_windows (display->x11_display);
|
|
|
|
}
|
|
|
|
|
2022-07-15 05:06:12 -04:00
|
|
|
static MetaCompositorView *
|
|
|
|
meta_compositor_create_view (MetaCompositor *compositor,
|
|
|
|
ClutterStageView *stage_view)
|
|
|
|
{
|
|
|
|
return META_COMPOSITOR_GET_CLASS (compositor)->create_view (compositor,
|
|
|
|
stage_view);
|
|
|
|
}
|
|
|
|
|
2020-03-03 03:27:33 -05:00
|
|
|
gboolean
|
|
|
|
meta_compositor_do_manage (MetaCompositor *compositor,
|
|
|
|
GError **error)
|
2013-03-01 14:41:11 -05:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
MetaDisplay *display = priv->display;
|
2020-04-16 13:14:21 -04:00
|
|
|
MetaBackend *backend = priv->backend;
|
|
|
|
ClutterActor *stage = meta_backend_get_stage (backend);
|
2013-03-02 07:15:23 -05:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->stage_presented_id =
|
2020-04-16 13:14:21 -04:00
|
|
|
g_signal_connect (stage, "presented",
|
2019-04-29 16:02:18 -04:00
|
|
|
G_CALLBACK (on_presented),
|
2019-08-14 13:46:35 -04:00
|
|
|
compositor);
|
2016-06-08 01:07:09 -04:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->window_group = meta_window_group_new (display);
|
|
|
|
priv->top_window_group = meta_window_group_new (display);
|
|
|
|
priv->feedback_group = meta_window_group_new (display);
|
2008-10-02 07:16:15 -04:00
|
|
|
|
2020-04-16 13:14:21 -04:00
|
|
|
clutter_actor_add_child (stage, priv->window_group);
|
|
|
|
clutter_actor_add_child (stage, priv->top_window_group);
|
|
|
|
clutter_actor_add_child (stage, priv->feedback_group);
|
2008-10-02 07:16:15 -04:00
|
|
|
|
2020-03-03 03:27:33 -05:00
|
|
|
if (!META_COMPOSITOR_GET_CLASS (compositor)->manage (compositor, error))
|
|
|
|
return FALSE;
|
2013-11-19 15:37:31 -05:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->plugin_mgr = meta_plugin_manager_new (compositor);
|
2022-01-18 13:25:57 -05:00
|
|
|
meta_plugin_manager_start (priv->plugin_mgr);
|
2020-03-03 03:27:33 -05:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_manage (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
if (!meta_compositor_do_manage (compositor, &error))
|
|
|
|
g_error ("Compositor failed to manage display: %s", error->message);
|
2008-06-04 08:58:36 -04:00
|
|
|
}
|
|
|
|
|
2022-01-28 18:15:28 -05:00
|
|
|
static void
|
|
|
|
meta_compositor_real_unmanage (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
g_clear_signal_handler (&priv->top_window_actor_destroy_id,
|
|
|
|
priv->top_window_actor);
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->window_group, clutter_actor_destroy);
|
|
|
|
g_clear_pointer (&priv->top_window_group, clutter_actor_destroy);
|
|
|
|
g_clear_pointer (&priv->feedback_group, clutter_actor_destroy);
|
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
2014-03-18 17:31:22 -04:00
|
|
|
meta_compositor_unmanage (MetaCompositor *compositor)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2019-08-14 17:25:54 -04:00
|
|
|
META_COMPOSITOR_GET_CLASS (compositor)->unmanage (compositor);
|
2013-12-06 17:10:44 -05:00
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
|
|
|
meta_compositor_add_window (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2018-12-22 09:21:34 -05:00
|
|
|
MetaWindowActor *window_actor;
|
|
|
|
ClutterActor *window_group;
|
2019-01-07 06:35:29 -05:00
|
|
|
GType window_actor_type = G_TYPE_INVALID;
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2018-12-22 09:21:34 -05:00
|
|
|
switch (window->client_type)
|
|
|
|
{
|
|
|
|
case META_WINDOW_CLIENT_TYPE_X11:
|
|
|
|
window_actor_type = META_TYPE_WINDOW_ACTOR_X11;
|
|
|
|
break;
|
|
|
|
|
2019-09-28 04:26:21 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
2018-12-22 09:21:34 -05:00
|
|
|
case META_WINDOW_CLIENT_TYPE_WAYLAND:
|
|
|
|
window_actor_type = META_TYPE_WINDOW_ACTOR_WAYLAND;
|
|
|
|
break;
|
2019-09-28 04:26:21 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_return_if_reached ();
|
2018-12-22 09:21:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
window_actor = g_object_new (window_actor_type,
|
|
|
|
"meta-window", window,
|
2020-02-18 17:01:28 -05:00
|
|
|
"show-on-set-parent", FALSE,
|
2018-12-22 09:21:34 -05:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (window->layer == META_LAYER_OVERRIDE_REDIRECT)
|
2019-08-14 13:04:41 -04:00
|
|
|
window_group = priv->top_window_group;
|
2018-12-22 09:21:34 -05:00
|
|
|
else
|
2019-08-14 13:04:41 -04:00
|
|
|
window_group = priv->window_group;
|
2018-12-22 09:21:34 -05:00
|
|
|
|
|
|
|
clutter_actor_add_child (window_group, CLUTTER_ACTOR (window_actor));
|
|
|
|
|
|
|
|
/* Initial position in the stack is arbitrary; stacking will be synced
|
|
|
|
* before we first paint.
|
|
|
|
*/
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->windows = g_list_append (priv->windows, window_actor);
|
2014-03-18 17:31:22 -04:00
|
|
|
sync_actor_stacking (compositor);
|
2008-06-04 08:58:36 -04:00
|
|
|
}
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
static void
|
|
|
|
meta_compositor_real_remove_window (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2019-07-26 17:03:00 -04:00
|
|
|
MetaWindowActor *window_actor = meta_window_actor_from_window (window);
|
2012-01-07 17:21:32 -05:00
|
|
|
|
2017-11-30 22:17:02 -05:00
|
|
|
meta_window_actor_queue_destroy (window_actor);
|
2008-06-04 08:58:36 -04:00
|
|
|
}
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
void
|
|
|
|
meta_compositor_remove_window (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
|
|
|
META_COMPOSITOR_GET_CLASS (compositor)->remove_window (compositor, window);
|
|
|
|
}
|
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
void
|
|
|
|
meta_compositor_remove_window_actor (MetaCompositor *compositor,
|
|
|
|
MetaWindowActor *window_actor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
priv->windows = g_list_remove (priv->windows, window_actor);
|
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
2014-06-17 13:06:10 -04:00
|
|
|
meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2019-07-26 17:03:00 -04:00
|
|
|
MetaWindowActor *window_actor = meta_window_actor_from_window (window);
|
|
|
|
|
2014-06-17 13:06:10 -04:00
|
|
|
meta_window_actor_sync_updates_frozen (window_actor);
|
2008-06-04 08:58:36 -04:00
|
|
|
}
|
|
|
|
|
2013-02-14 13:40:55 -05:00
|
|
|
void
|
|
|
|
meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
gboolean no_delay_frame)
|
|
|
|
{
|
2019-07-26 17:03:00 -04:00
|
|
|
MetaWindowActor *window_actor = meta_window_actor_from_window (window);
|
|
|
|
|
2013-02-14 13:40:55 -05:00
|
|
|
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
|
|
|
|
}
|
|
|
|
|
2011-07-20 00:29:06 -04:00
|
|
|
void
|
2014-02-26 20:45:38 -05:00
|
|
|
meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
2013-08-23 22:20:49 -04:00
|
|
|
MetaWindow *window)
|
2011-07-20 00:29:06 -04:00
|
|
|
{
|
|
|
|
MetaWindowActor *window_actor;
|
2019-07-26 17:03:00 -04:00
|
|
|
|
|
|
|
window_actor = meta_window_actor_from_window (window);
|
2013-03-13 22:34:20 -04:00
|
|
|
if (!window_actor)
|
|
|
|
return;
|
|
|
|
|
2019-08-17 04:00:46 -04:00
|
|
|
meta_window_actor_x11_update_shape (META_WINDOW_ACTOR_X11 (window_actor));
|
2011-07-20 00:29:06 -04:00
|
|
|
}
|
|
|
|
|
2013-12-06 13:44:31 -05:00
|
|
|
void
|
|
|
|
meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
|
|
|
MetaWindowActor *window_actor;
|
2019-07-26 17:03:00 -04:00
|
|
|
|
|
|
|
window_actor = meta_window_actor_from_window (window);
|
2013-12-06 13:44:31 -05:00
|
|
|
if (!window_actor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
meta_window_actor_update_opacity (window_actor);
|
|
|
|
}
|
|
|
|
|
2022-07-02 15:51:13 -04:00
|
|
|
static void
|
|
|
|
invalidate_top_window_actor_for_views (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
g_assert (!priv->frame_in_progress);
|
|
|
|
|
|
|
|
priv->needs_update_top_window_actors = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_window_actor_stage_views_changed (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
invalidate_top_window_actor_for_views (compositor);
|
|
|
|
}
|
|
|
|
|
2012-08-09 20:27:18 -04:00
|
|
|
gboolean
|
|
|
|
meta_compositor_filter_keybinding (MetaCompositor *compositor,
|
|
|
|
MetaKeyBinding *binding)
|
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return meta_plugin_manager_filter_keybinding (priv->plugin_mgr, binding);
|
2012-08-09 20:27:18 -04:00
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
meta_compositor_show_window (MetaCompositor *compositor,
|
2019-06-13 04:39:31 -04:00
|
|
|
MetaWindow *window,
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
MetaCompEffect effect)
|
2008-06-09 12:50:56 -04:00
|
|
|
{
|
2019-07-26 17:03:00 -04:00
|
|
|
MetaWindowActor *window_actor = meta_window_actor_from_window (window);
|
|
|
|
|
|
|
|
meta_window_actor_show (window_actor, effect);
|
2008-11-23 14:28:40 -05:00
|
|
|
}
|
2008-06-09 12:50:56 -04:00
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
meta_compositor_hide_window (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaCompEffect effect)
|
2008-11-23 14:28:40 -05:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2019-07-26 17:03:00 -04:00
|
|
|
MetaWindowActor *window_actor = meta_window_actor_from_window (window);
|
|
|
|
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_window_actor_hide (window_actor, effect);
|
2019-08-14 13:04:41 -04:00
|
|
|
meta_stack_tracker_queue_sync_stack (priv->display->stack_tracker);
|
2008-06-09 12:50:56 -04:00
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
2015-07-06 00:08:08 -04:00
|
|
|
meta_compositor_size_change_window (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaSizeChange which_change,
|
|
|
|
MetaRectangle *old_frame_rect,
|
|
|
|
MetaRectangle *old_buffer_rect)
|
2008-08-19 06:47:30 -04:00
|
|
|
{
|
2019-07-26 17:03:00 -04:00
|
|
|
MetaWindowActor *window_actor = meta_window_actor_from_window (window);
|
|
|
|
|
2015-10-12 11:55:51 -04:00
|
|
|
meta_window_actor_size_change (window_actor, which_change, old_frame_rect, old_buffer_rect);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
|
|
|
meta_compositor_switch_workspace (MetaCompositor *compositor,
|
|
|
|
MetaWorkspace *from,
|
|
|
|
MetaWorkspace *to,
|
|
|
|
MetaMotionDirection direction)
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2014-03-18 17:31:22 -04:00
|
|
|
gint to_indx, from_indx;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
|
|
|
to_indx = meta_workspace_index (to);
|
|
|
|
from_indx = meta_workspace_index (from);
|
2008-11-07 05:13:40 -05:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->switch_workspace_in_progress++;
|
2008-09-18 11:09:11 -04:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
if (!meta_plugin_manager_switch_workspace (priv->plugin_mgr,
|
2014-03-18 17:31:22 -04:00
|
|
|
from_indx,
|
|
|
|
to_indx,
|
2014-03-18 18:12:29 -04:00
|
|
|
direction))
|
2008-09-18 11:09:11 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->switch_workspace_in_progress--;
|
2008-10-24 05:07:24 -04:00
|
|
|
|
2020-08-26 05:49:50 -04:00
|
|
|
/* We have to explicitly call this to fix up stacking order of the
|
2008-10-24 05:07:24 -04:00
|
|
|
* actors; this is because the abs stacking position of actors does not
|
|
|
|
* necessarily change during the window hiding/unhiding, only their
|
|
|
|
* relative position toward the destkop window.
|
|
|
|
*/
|
2014-03-18 17:31:22 -04:00
|
|
|
meta_finish_workspace_switch (compositor);
|
2008-09-18 11:09:11 -04:00
|
|
|
}
|
2008-08-19 06:47:30 -04:00
|
|
|
}
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2008-11-23 14:28:40 -05:00
|
|
|
static void
|
2014-03-18 17:31:22 -04:00
|
|
|
sync_actor_stacking (MetaCompositor *compositor)
|
2008-11-23 14:28:40 -05:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2010-11-13 14:45:01 -05:00
|
|
|
GList *children;
|
2013-02-13 23:10:33 -05:00
|
|
|
GList *expected_window_node;
|
2008-11-23 14:28:40 -05:00
|
|
|
GList *tmp;
|
2010-11-13 14:45:01 -05:00
|
|
|
GList *old;
|
2013-01-23 15:54:41 -05:00
|
|
|
GList *backgrounds;
|
2013-02-13 23:10:33 -05:00
|
|
|
gboolean has_windows;
|
2010-11-13 14:45:01 -05:00
|
|
|
gboolean reordered;
|
2008-12-18 07:41:56 -05:00
|
|
|
|
2010-11-13 14:45:01 -05:00
|
|
|
/* NB: The first entries in the lists are stacked the lowest */
|
2008-11-23 14:28:40 -05:00
|
|
|
|
2010-11-13 14:45:01 -05:00
|
|
|
/* Restacking will trigger full screen redraws, so it's worth a
|
|
|
|
* little effort to make sure we actually need to restack before
|
|
|
|
* we go ahead and do it */
|
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
children = clutter_actor_get_children (priv->window_group);
|
2013-09-03 16:03:17 -04:00
|
|
|
has_windows = FALSE;
|
2010-11-13 14:45:01 -05:00
|
|
|
reordered = FALSE;
|
|
|
|
|
2010-11-14 12:37:17 -05:00
|
|
|
/* We allow for actors in the window group other than the actors we
|
|
|
|
* know about, but it's up to a plugin to try and keep them stacked correctly
|
|
|
|
* (we really need extra API to make that reliable.)
|
|
|
|
*/
|
|
|
|
|
2013-01-23 15:54:41 -05:00
|
|
|
/* First we collect a list of all backgrounds, and check if they're at the
|
|
|
|
* bottom. Then we check if the window actors are in the correct sequence */
|
|
|
|
backgrounds = NULL;
|
2019-08-14 13:04:41 -04:00
|
|
|
expected_window_node = priv->windows;
|
2013-02-13 23:10:33 -05:00
|
|
|
for (old = children; old != NULL; old = old->next)
|
2010-11-14 12:37:17 -05:00
|
|
|
{
|
2013-02-13 23:10:33 -05:00
|
|
|
ClutterActor *actor = old->data;
|
2010-11-14 12:37:17 -05:00
|
|
|
|
2013-01-23 15:54:41 -05:00
|
|
|
if (META_IS_BACKGROUND_GROUP (actor) ||
|
|
|
|
META_IS_BACKGROUND_ACTOR (actor))
|
2010-11-13 14:45:01 -05:00
|
|
|
{
|
2013-01-23 15:54:41 -05:00
|
|
|
backgrounds = g_list_prepend (backgrounds, actor);
|
|
|
|
|
2013-02-13 23:10:33 -05:00
|
|
|
if (has_windows)
|
|
|
|
reordered = TRUE;
|
2010-11-13 14:45:01 -05:00
|
|
|
}
|
2013-02-13 23:10:33 -05:00
|
|
|
else if (META_IS_WINDOW_ACTOR (actor) && !reordered)
|
|
|
|
{
|
|
|
|
has_windows = TRUE;
|
2010-11-13 14:45:01 -05:00
|
|
|
|
2013-02-13 23:10:33 -05:00
|
|
|
if (expected_window_node != NULL && actor == expected_window_node->data)
|
|
|
|
expected_window_node = expected_window_node->next;
|
|
|
|
else
|
|
|
|
reordered = TRUE;
|
|
|
|
}
|
2010-11-13 14:45:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free (children);
|
|
|
|
|
|
|
|
if (!reordered)
|
2013-01-23 15:54:41 -05:00
|
|
|
{
|
|
|
|
g_list_free (backgrounds);
|
|
|
|
return;
|
|
|
|
}
|
2010-11-13 14:45:01 -05:00
|
|
|
|
2013-02-13 23:10:33 -05:00
|
|
|
/* reorder the actors by lowering them in turn to the bottom of the stack.
|
2013-03-12 12:01:51 -04:00
|
|
|
* windows first, then background.
|
|
|
|
*
|
|
|
|
* We reorder the actors even if they're not parented to the window group,
|
|
|
|
* to allow stacking to work with intermediate actors (eg during effects)
|
|
|
|
*/
|
2019-08-14 13:04:41 -04:00
|
|
|
for (tmp = g_list_last (priv->windows); tmp != NULL; tmp = tmp->prev)
|
2008-11-23 14:28:40 -05:00
|
|
|
{
|
2013-03-12 12:01:51 -04:00
|
|
|
ClutterActor *actor = tmp->data, *parent;
|
2008-11-23 14:28:40 -05:00
|
|
|
|
2013-03-12 12:01:51 -04:00
|
|
|
parent = clutter_actor_get_parent (actor);
|
|
|
|
clutter_actor_set_child_below_sibling (parent, actor, NULL);
|
2008-11-23 14:28:40 -05:00
|
|
|
}
|
2010-11-14 12:37:17 -05:00
|
|
|
|
2013-01-23 15:54:41 -05:00
|
|
|
/* we prepended the backgrounds above so the last actor in the list
|
|
|
|
* should get lowered to the bottom last.
|
|
|
|
*/
|
|
|
|
for (tmp = backgrounds; tmp != NULL; tmp = tmp->next)
|
|
|
|
{
|
2013-03-12 12:01:51 -04:00
|
|
|
ClutterActor *actor = tmp->data, *parent;
|
2013-01-23 15:54:41 -05:00
|
|
|
|
2013-03-12 12:01:51 -04:00
|
|
|
parent = clutter_actor_get_parent (actor);
|
|
|
|
clutter_actor_set_child_below_sibling (parent, actor, NULL);
|
2013-01-23 15:54:41 -05:00
|
|
|
}
|
|
|
|
g_list_free (backgrounds);
|
2008-11-23 14:28:40 -05:00
|
|
|
}
|
|
|
|
|
2017-10-13 04:29:20 -04:00
|
|
|
/*
|
|
|
|
* Find the top most window that is visible on the screen. The intention of
|
|
|
|
* this is to avoid offscreen windows that isn't actually part of the visible
|
|
|
|
* desktop (such as the UI frames override redirect window).
|
|
|
|
*/
|
2022-05-12 11:39:56 -04:00
|
|
|
static void
|
|
|
|
update_top_window_actor (MetaCompositor *compositor)
|
2017-10-13 04:29:20 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2017-10-13 04:29:20 -04:00
|
|
|
GList *l;
|
2022-05-12 11:39:56 -04:00
|
|
|
MetaWindowActor *top_window_actor = NULL;
|
2017-10-13 04:29:20 -04:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
for (l = g_list_last (priv->windows); l; l = l->prev)
|
2017-10-13 04:29:20 -04:00
|
|
|
{
|
|
|
|
MetaWindowActor *window_actor = l->data;
|
|
|
|
MetaWindow *window = meta_window_actor_get_meta_window (window_actor);
|
|
|
|
MetaRectangle buffer_rect;
|
2017-08-27 14:44:38 -04:00
|
|
|
MetaRectangle display_rect = { 0 };
|
2017-10-13 04:29:20 -04:00
|
|
|
|
2018-09-19 10:08:52 -04:00
|
|
|
if (!window->visible_to_compositor)
|
|
|
|
continue;
|
|
|
|
|
2017-10-13 04:29:20 -04:00
|
|
|
meta_window_get_buffer_rect (window, &buffer_rect);
|
2019-08-14 13:04:41 -04:00
|
|
|
meta_display_get_size (priv->display,
|
2017-08-27 14:44:38 -04:00
|
|
|
&display_rect.width, &display_rect.height);
|
2017-10-13 04:29:20 -04:00
|
|
|
|
2017-08-27 14:44:38 -04:00
|
|
|
if (meta_rectangle_overlap (&display_rect, &buffer_rect))
|
2022-05-12 11:39:56 -04:00
|
|
|
{
|
|
|
|
top_window_actor = window_actor;
|
|
|
|
break;
|
|
|
|
}
|
2017-10-13 04:29:20 -04:00
|
|
|
}
|
|
|
|
|
2022-05-12 11:39:56 -04:00
|
|
|
if (priv->top_window_actor == top_window_actor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_clear_signal_handler (&priv->top_window_actor_destroy_id,
|
|
|
|
priv->top_window_actor);
|
|
|
|
|
|
|
|
priv->top_window_actor = top_window_actor;
|
|
|
|
|
|
|
|
if (priv->top_window_actor)
|
|
|
|
{
|
|
|
|
priv->top_window_actor_destroy_id =
|
|
|
|
g_signal_connect (priv->top_window_actor, "destroy",
|
|
|
|
G_CALLBACK (on_top_window_actor_destroyed),
|
|
|
|
compositor);
|
|
|
|
}
|
2017-10-13 04:29:20 -04:00
|
|
|
}
|
|
|
|
|
2017-11-29 18:05:27 -05:00
|
|
|
static void
|
|
|
|
on_top_window_actor_destroyed (MetaWindowActor *window_actor,
|
|
|
|
MetaCompositor *compositor)
|
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2017-11-29 18:05:27 -05:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->top_window_actor = NULL;
|
|
|
|
priv->top_window_actor_destroy_id = 0;
|
|
|
|
priv->windows = g_list_remove (priv->windows, window_actor);
|
|
|
|
|
|
|
|
meta_stack_tracker_queue_sync_stack (priv->display->stack_tracker);
|
2017-11-29 18:05:27 -05:00
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
|
|
|
meta_compositor_sync_stack (MetaCompositor *compositor,
|
2019-06-13 04:39:31 -04:00
|
|
|
GList *stack)
|
2008-10-24 05:07:24 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2009-06-26 17:05:11 -04:00
|
|
|
GList *old_stack;
|
2008-11-27 08:40:52 -05:00
|
|
|
|
2009-06-26 17:05:11 -04:00
|
|
|
/* This is painful because hidden windows that we are in the process
|
|
|
|
* of animating out of existence. They'll be at the bottom of the
|
|
|
|
* stack of X windows, but we want to leave them in their old position
|
|
|
|
* until the animation effect finishes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Sources: first window is the highest */
|
|
|
|
stack = g_list_copy (stack); /* The new stack of MetaWindow */
|
2019-08-14 13:04:41 -04:00
|
|
|
old_stack = g_list_reverse (priv->windows); /* The old stack of MetaWindowActor */
|
|
|
|
priv->windows = NULL;
|
2009-06-26 17:05:11 -04:00
|
|
|
|
|
|
|
while (TRUE)
|
2008-10-24 05:07:24 -04:00
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
MetaWindowActor *old_actor = NULL, *stack_actor = NULL, *actor;
|
2009-06-26 17:05:11 -04:00
|
|
|
MetaWindow *old_window = NULL, *stack_window = NULL, *window;
|
2008-11-03 09:50:22 -05:00
|
|
|
|
2009-06-26 17:05:11 -04:00
|
|
|
/* Find the remaining top actor in our existing stack (ignoring
|
|
|
|
* windows that have been hidden and are no longer animating) */
|
|
|
|
while (old_stack)
|
|
|
|
{
|
|
|
|
old_actor = old_stack->data;
|
2010-10-18 13:27:14 -04:00
|
|
|
old_window = meta_window_actor_get_meta_window (old_actor);
|
2009-06-26 17:05:11 -04:00
|
|
|
|
2014-09-10 16:24:26 -04:00
|
|
|
if ((old_window->hidden || old_window->unmanaging) &&
|
2010-10-18 13:27:14 -04:00
|
|
|
!meta_window_actor_effect_in_progress (old_actor))
|
2011-01-26 16:35:18 -05:00
|
|
|
{
|
|
|
|
old_stack = g_list_delete_link (old_stack, old_stack);
|
|
|
|
old_actor = NULL;
|
|
|
|
}
|
2009-06-26 17:05:11 -04:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And the remaining top actor in the new stack */
|
|
|
|
while (stack)
|
|
|
|
{
|
|
|
|
stack_window = stack->data;
|
2019-07-26 17:03:00 -04:00
|
|
|
stack_actor = meta_window_actor_from_window (stack_window);
|
2009-06-26 17:05:11 -04:00
|
|
|
if (!stack_actor)
|
|
|
|
{
|
2010-10-18 13:27:14 -04:00
|
|
|
meta_verbose ("Failed to find corresponding MetaWindowActor "
|
2020-10-02 11:47:22 -04:00
|
|
|
"for window %s", meta_window_get_description (stack_window));
|
2009-06-26 17:05:11 -04:00
|
|
|
stack = g_list_delete_link (stack, stack);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!old_actor && !stack_actor) /* Nothing more to stack */
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* We usually prefer the window in the new stack, but if if we
|
|
|
|
* found a hidden window in the process of being animated out
|
|
|
|
* of existence in the old stack we use that instead. We've
|
|
|
|
* filtered out non-animating hidden windows above.
|
|
|
|
*/
|
|
|
|
if (old_actor &&
|
2014-09-10 16:24:26 -04:00
|
|
|
(!stack_actor || old_window->hidden || old_window->unmanaging))
|
2009-06-26 17:05:11 -04:00
|
|
|
{
|
|
|
|
actor = old_actor;
|
|
|
|
window = old_window;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
actor = stack_actor;
|
|
|
|
window = stack_window;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* OK, we know what actor we want next. Add it to our window
|
|
|
|
* list, and remove it from both source lists. (It will
|
|
|
|
* be at the front of at least one, hopefully it will be
|
|
|
|
* near the front of the other.)
|
|
|
|
*/
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->windows = g_list_prepend (priv->windows, actor);
|
2008-11-07 05:13:40 -05:00
|
|
|
|
2009-06-26 17:05:11 -04:00
|
|
|
stack = g_list_remove (stack, window);
|
|
|
|
old_stack = g_list_remove (old_stack, actor);
|
2008-11-03 09:50:22 -05:00
|
|
|
}
|
2008-11-23 14:28:40 -05:00
|
|
|
|
2014-03-18 17:31:22 -04:00
|
|
|
sync_actor_stacking (compositor);
|
2017-10-13 04:29:20 -04:00
|
|
|
|
2022-05-12 11:39:56 -04:00
|
|
|
update_top_window_actor (compositor);
|
2022-07-02 15:51:13 -04:00
|
|
|
invalidate_top_window_actor_for_views (compositor);
|
2008-11-03 09:50:22 -05:00
|
|
|
}
|
|
|
|
|
2009-06-25 16:17:27 -04:00
|
|
|
void
|
|
|
|
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
2019-06-13 04:39:31 -04:00
|
|
|
MetaWindow *window,
|
|
|
|
gboolean did_placement)
|
2008-11-27 08:40:52 -05:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2019-07-26 17:03:00 -04:00
|
|
|
MetaWindowActor *window_actor = meta_window_actor_from_window (window);
|
2019-05-07 06:08:13 -04:00
|
|
|
MetaWindowActorChanges changes;
|
|
|
|
|
|
|
|
changes = meta_window_actor_sync_actor_geometry (window_actor, did_placement);
|
|
|
|
|
|
|
|
if (changes & META_WINDOW_ACTOR_CHANGE_SIZE)
|
2019-08-14 13:04:41 -04:00
|
|
|
meta_plugin_manager_event_size_changed (priv->plugin_mgr, window_actor);
|
2008-11-27 08:40:52 -05:00
|
|
|
}
|
|
|
|
|
2022-07-02 15:51:13 -04:00
|
|
|
static void
|
|
|
|
maybe_update_top_window_actor_for_views (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
ClutterStage *stage;
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (!priv->needs_update_top_window_actors)
|
|
|
|
return;
|
|
|
|
|
|
|
|
priv->needs_update_top_window_actors = FALSE;
|
|
|
|
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (UpdateTopWindowActorForViews,
|
|
|
|
"Compositor (update top window actors)");
|
|
|
|
|
|
|
|
stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
|
|
|
|
|
|
|
|
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
|
|
|
|
{
|
|
|
|
ClutterStageView *stage_view = l->data;
|
|
|
|
MetaCompositorView *compositor_view;
|
|
|
|
|
|
|
|
compositor_view = g_object_get_qdata (G_OBJECT (stage_view),
|
|
|
|
quark_compositor_view);
|
|
|
|
|
|
|
|
g_assert (compositor_view != NULL);
|
|
|
|
|
|
|
|
meta_compositor_view_update_top_window_actor (compositor_view,
|
|
|
|
priv->windows);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-10 07:44:34 -04:00
|
|
|
static void
|
|
|
|
meta_compositor_ensure_compositor_views (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
ClutterStage *stage =
|
|
|
|
CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
|
|
|
|
{
|
|
|
|
ClutterStageView *stage_view = l->data;
|
|
|
|
MetaCompositorView *compositor_view;
|
|
|
|
|
|
|
|
compositor_view = g_object_get_qdata (G_OBJECT (stage_view),
|
|
|
|
quark_compositor_view);
|
|
|
|
|
|
|
|
if (compositor_view)
|
|
|
|
continue;
|
|
|
|
|
2022-07-15 05:06:12 -04:00
|
|
|
compositor_view = meta_compositor_create_view (compositor,
|
|
|
|
stage_view);
|
2022-07-10 07:44:34 -04:00
|
|
|
|
|
|
|
g_object_set_qdata_full (G_OBJECT (stage_view),
|
|
|
|
quark_compositor_view,
|
|
|
|
compositor_view,
|
|
|
|
g_object_unref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-12 14:11:08 -05:00
|
|
|
static void
|
2016-06-08 01:07:09 -04:00
|
|
|
on_presented (ClutterStage *stage,
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
ClutterStageView *stage_view,
|
2016-06-08 01:07:09 -04:00
|
|
|
ClutterFrameInfo *frame_info,
|
|
|
|
MetaCompositor *compositor)
|
2012-11-12 14:11:08 -05:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2021-01-30 15:14:55 -05:00
|
|
|
int64_t presentation_time = frame_info->presentation_time;
|
2012-11-12 14:11:08 -05:00
|
|
|
GList *l;
|
|
|
|
|
2020-05-29 17:02:20 -04:00
|
|
|
for (l = priv->windows; l; l = l->next)
|
|
|
|
{
|
|
|
|
ClutterActor *actor = l->data;
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
GList *actor_stage_views;
|
2012-11-12 14:11:08 -05:00
|
|
|
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
actor_stage_views = clutter_actor_peek_stage_views (actor);
|
|
|
|
if (g_list_find (actor_stage_views, stage_view))
|
|
|
|
{
|
|
|
|
meta_window_actor_frame_complete (META_WINDOW_ACTOR (actor),
|
|
|
|
frame_info,
|
|
|
|
presentation_time);
|
|
|
|
}
|
2012-11-12 14:11:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
static void
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
meta_compositor_real_before_paint (MetaCompositor *compositor,
|
|
|
|
MetaCompositorView *compositor_view)
|
2009-06-28 12:26:23 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
ClutterStageView *stage_view;
|
2009-06-28 12:26:23 -04:00
|
|
|
GList *l;
|
|
|
|
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
stage_view = meta_compositor_view_get_stage_view (compositor_view);
|
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
for (l = priv->windows; l; l = l->next)
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
meta_window_actor_before_paint (l->data, stage_view);
|
2019-08-14 17:25:54 -04:00
|
|
|
}
|
2014-05-12 09:11:53 -04:00
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
static void
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
meta_compositor_before_paint (MetaCompositor *compositor,
|
|
|
|
MetaCompositorView *compositor_view)
|
2019-08-14 17:25:54 -04:00
|
|
|
{
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
2019-08-27 06:14:21 -04:00
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaCompositorPrePaint,
|
2020-05-29 18:02:42 -04:00
|
|
|
"Compositor (before-paint)");
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
|
2022-07-02 15:51:13 -04:00
|
|
|
maybe_update_top_window_actor_for_views (compositor);
|
|
|
|
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
priv->frame_in_progress = TRUE;
|
|
|
|
|
|
|
|
META_COMPOSITOR_GET_CLASS (compositor)->before_paint (compositor, compositor_view);
|
2019-08-14 17:25:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
meta_compositor_real_after_paint (MetaCompositor *compositor,
|
|
|
|
MetaCompositorView *compositor_view)
|
2019-08-14 17:25:54 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2020-07-17 03:16:09 -04:00
|
|
|
ClutterActor *stage_actor = meta_backend_get_stage (priv->backend);
|
2016-05-20 13:22:23 -04:00
|
|
|
CoglGraphicsResetStatus status;
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
ClutterStageView *stage_view;
|
2020-05-29 18:02:42 -04:00
|
|
|
GList *l;
|
2014-04-18 14:21:20 -04:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
status = cogl_get_graphics_reset_status (priv->context);
|
2016-05-20 13:22:23 -04:00
|
|
|
switch (status)
|
|
|
|
{
|
|
|
|
case COGL_GRAPHICS_RESET_STATUS_NO_ERROR:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET:
|
2019-08-14 13:04:41 -04:00
|
|
|
g_signal_emit_by_name (priv->display, "gl-video-memory-purged");
|
2020-07-17 03:16:09 -04:00
|
|
|
g_signal_emit_by_name (stage_actor, "gl-video-memory-purged");
|
|
|
|
clutter_actor_queue_redraw (stage_actor);
|
2016-05-20 13:22:23 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* The ARB_robustness spec says that, on error, the application
|
|
|
|
should destroy the old context and create a new one. Since we
|
|
|
|
don't have the necessary plumbing to do this we'll simply
|
|
|
|
restart the process. Obviously we can't do this when we are
|
|
|
|
a wayland compositor but in that case we shouldn't get here
|
|
|
|
since we don't enable robustness in that case. */
|
|
|
|
g_assert (!meta_is_wayland_compositor ());
|
2022-05-30 17:06:00 -04:00
|
|
|
meta_restart (NULL, meta_display_get_context (priv->display));
|
2016-05-20 13:22:23 -04:00
|
|
|
break;
|
|
|
|
}
|
2020-05-29 18:02:42 -04:00
|
|
|
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
stage_view = meta_compositor_view_get_stage_view (compositor_view);
|
|
|
|
|
2020-05-29 18:02:42 -04:00
|
|
|
for (l = priv->windows; l; l = l->next)
|
|
|
|
{
|
|
|
|
ClutterActor *actor = l->data;
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
GList *actor_stage_views;
|
2020-05-29 18:02:42 -04:00
|
|
|
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
actor_stage_views = clutter_actor_peek_stage_views (actor);
|
|
|
|
if (g_list_find (actor_stage_views, stage_view))
|
|
|
|
meta_window_actor_after_paint (META_WINDOW_ACTOR (actor), stage_view);
|
2020-05-29 18:02:42 -04:00
|
|
|
}
|
2019-08-14 17:25:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
meta_compositor_after_paint (MetaCompositor *compositor,
|
|
|
|
MetaCompositorView *compositor_view)
|
2019-08-14 17:25:54 -04:00
|
|
|
{
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
2019-08-27 06:14:21 -04:00
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaCompositorPostPaint,
|
2020-05-29 18:02:42 -04:00
|
|
|
"Compositor (after-paint)");
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
META_COMPOSITOR_GET_CLASS (compositor)->after_paint (compositor, compositor_view);
|
|
|
|
|
|
|
|
priv->frame_in_progress = FALSE;
|
2019-08-14 17:25:54 -04:00
|
|
|
}
|
|
|
|
|
2020-05-29 18:02:42 -04:00
|
|
|
static void
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
on_before_paint (ClutterStage *stage,
|
|
|
|
ClutterStageView *stage_view,
|
|
|
|
MetaCompositor *compositor)
|
2019-08-14 17:25:54 -04:00
|
|
|
{
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
MetaCompositorView *compositor_view;
|
|
|
|
|
|
|
|
compositor_view = g_object_get_qdata (G_OBJECT (stage_view),
|
|
|
|
quark_compositor_view);
|
|
|
|
|
|
|
|
g_assert (compositor_view != NULL);
|
|
|
|
|
|
|
|
meta_compositor_before_paint (compositor, compositor_view);
|
2020-05-29 18:02:42 -04:00
|
|
|
}
|
2016-05-20 13:22:23 -04:00
|
|
|
|
2020-05-29 18:02:42 -04:00
|
|
|
static void
|
clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.
For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.
This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.
Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/903
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-05-29 18:27:56 -04:00
|
|
|
on_after_paint (ClutterStage *stage,
|
|
|
|
ClutterStageView *stage_view,
|
|
|
|
MetaCompositor *compositor)
|
2020-05-29 18:02:42 -04:00
|
|
|
{
|
compositor: Expose the MetaCompositorView in before_paint () vfunc
The idea is that the state of the MetaCompositorView shall be
up-to-date only in specific scenarios, thus allowing operations
performed on it to be queued and aggregated to be handled in the
right time, and only if they are still necessary.
For example, in a following commit, the top window actor in each
view will be planned (if needed) only once before painting a frame,
rendering the top window actor in the MetaCompositorView potentially
stale in all other times.
Similarly, if a MetaCompositorView is destroyed before the beginning
of the frame, a queued operation to update its top window actor can be
discarded.
As an interface segragation measure, and as part of an attempt to
avoid the use of g_return_if_fail () to check the validity of the
MetaCompositorView's state in multiple places (which is still prone to
human error), the interfaces through which a MetaCompositorView is
made available would only ones where it's state is gurenteed to be
up-to-date.
Specifically, this commit gurentees that the state of the
MetaCompositorView would be up-to-date during the before_paint () and
after_paint () vfuncs exposed to child classes of the MetaCompositor.
The frame_in_progress variable will be used in a following commit to
guarantee that the MetaCompositorView's state is not invalidated during
this time.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>
2022-07-11 05:23:24 -04:00
|
|
|
MetaCompositorView *compositor_view;
|
|
|
|
|
|
|
|
compositor_view = g_object_get_qdata (G_OBJECT (stage_view),
|
|
|
|
quark_compositor_view);
|
|
|
|
|
|
|
|
g_assert (compositor_view != NULL);
|
|
|
|
|
|
|
|
meta_compositor_after_paint (compositor, compositor_view);
|
2009-06-28 12:26:23 -04:00
|
|
|
}
|
|
|
|
|
2022-05-12 11:42:20 -04:00
|
|
|
static void
|
|
|
|
on_window_visibility_updated (MetaDisplay *display,
|
|
|
|
GList *unplaced,
|
|
|
|
GList *should_show,
|
|
|
|
GList *should_hide,
|
|
|
|
MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
update_top_window_actor (compositor);
|
2022-07-02 15:51:13 -04:00
|
|
|
invalidate_top_window_actor_for_views (compositor);
|
2022-05-12 11:42:20 -04:00
|
|
|
}
|
|
|
|
|
2022-07-10 07:44:34 -04:00
|
|
|
static void
|
|
|
|
on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
|
|
|
|
MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
meta_compositor_ensure_compositor_views (compositor);
|
|
|
|
}
|
|
|
|
|
2019-08-19 04:24:17 -04:00
|
|
|
static void
|
|
|
|
meta_compositor_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2008-06-04 08:58:36 -04:00
|
|
|
{
|
2019-08-19 04:24:17 -04:00
|
|
|
MetaCompositor *compositor = META_COMPOSITOR (object);
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2019-08-19 04:24:17 -04:00
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_DISPLAY:
|
|
|
|
priv->display = g_value_get_object (value);
|
|
|
|
break;
|
2020-04-16 13:14:21 -04:00
|
|
|
case PROP_BACKEND:
|
|
|
|
priv->backend = g_value_get_object (value);
|
|
|
|
break;
|
2019-08-19 04:24:17 -04:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
|
|
|
}
|
2019-08-14 17:25:54 -04:00
|
|
|
|
2019-08-19 04:24:17 -04:00
|
|
|
static void
|
|
|
|
meta_compositor_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaCompositor *compositor = META_COMPOSITOR (object);
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2019-01-11 11:18:27 -05:00
|
|
|
|
2019-08-19 04:24:17 -04:00
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_DISPLAY:
|
|
|
|
g_value_set_object (value, priv->display);
|
|
|
|
break;
|
2020-04-16 13:14:21 -04:00
|
|
|
case PROP_BACKEND:
|
|
|
|
g_value_set_object (value, priv->backend);
|
|
|
|
break;
|
2019-08-19 04:24:17 -04:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
2019-01-11 11:18:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_compositor_init (MetaCompositor *compositor)
|
|
|
|
{
|
2022-07-02 15:51:13 -04:00
|
|
|
invalidate_top_window_actor_for_views (compositor);
|
2020-05-29 17:33:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_compositor_constructed (GObject *object)
|
|
|
|
{
|
|
|
|
MetaCompositor *compositor = META_COMPOSITOR (object);
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2020-05-29 17:33:46 -04:00
|
|
|
ClutterBackend *clutter_backend =
|
|
|
|
meta_backend_get_clutter_backend (priv->backend);
|
2020-05-29 18:02:42 -04:00
|
|
|
ClutterActor *stage = meta_backend_get_stage (priv->backend);
|
2022-07-10 07:44:34 -04:00
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (priv->backend);
|
2019-01-11 11:18:27 -05:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
priv->context = clutter_backend->cogl_context;
|
2008-06-04 08:58:36 -04:00
|
|
|
|
2020-05-29 18:02:42 -04:00
|
|
|
priv->before_paint_handler_id =
|
|
|
|
g_signal_connect (stage,
|
|
|
|
"before-paint",
|
|
|
|
G_CALLBACK (on_before_paint),
|
|
|
|
compositor);
|
|
|
|
priv->after_paint_handler_id =
|
|
|
|
g_signal_connect_after (stage,
|
|
|
|
"after-paint",
|
|
|
|
G_CALLBACK (on_after_paint),
|
|
|
|
compositor);
|
2020-03-03 03:32:33 -05:00
|
|
|
|
2022-05-12 11:42:20 -04:00
|
|
|
priv->window_visibility_updated_id =
|
|
|
|
g_signal_connect (priv->display,
|
|
|
|
"window-visibility-updated",
|
|
|
|
G_CALLBACK (on_window_visibility_updated),
|
|
|
|
compositor);
|
|
|
|
|
2022-07-10 07:44:34 -04:00
|
|
|
priv->monitors_changed_internal_id =
|
|
|
|
g_signal_connect (monitor_manager,
|
|
|
|
"monitors-changed-internal",
|
|
|
|
G_CALLBACK (on_monitors_changed_internal),
|
|
|
|
compositor);
|
|
|
|
|
2020-03-03 04:04:16 -05:00
|
|
|
priv->laters = meta_laters_new (compositor);
|
2020-05-29 17:33:46 -04:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_compositor_parent_class)->constructed (object);
|
2022-07-10 07:44:34 -04:00
|
|
|
|
|
|
|
meta_compositor_ensure_compositor_views (compositor);
|
2019-01-11 11:18:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_compositor_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
MetaCompositor *compositor = META_COMPOSITOR (object);
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
2020-04-16 13:14:21 -04:00
|
|
|
ClutterActor *stage = meta_backend_get_stage (priv->backend);
|
2019-01-11 11:18:27 -05:00
|
|
|
|
2020-03-03 03:32:33 -05:00
|
|
|
g_clear_pointer (&priv->laters, meta_laters_free);
|
|
|
|
|
2020-04-16 13:14:21 -04:00
|
|
|
g_clear_signal_handler (&priv->stage_presented_id, stage);
|
2020-05-29 18:02:42 -04:00
|
|
|
g_clear_signal_handler (&priv->before_paint_handler_id, stage);
|
|
|
|
g_clear_signal_handler (&priv->after_paint_handler_id, stage);
|
2022-05-12 11:42:20 -04:00
|
|
|
g_clear_signal_handler (&priv->window_visibility_updated_id, priv->display);
|
2019-01-11 11:18:27 -05:00
|
|
|
|
2019-08-14 13:04:41 -04:00
|
|
|
g_clear_pointer (&priv->windows, g_list_free);
|
2019-01-11 11:18:27 -05:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_compositor_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_compositor_class_init (MetaCompositorClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
2019-08-19 04:24:17 -04:00
|
|
|
object_class->set_property = meta_compositor_set_property;
|
|
|
|
object_class->get_property = meta_compositor_get_property;
|
2020-05-29 17:33:46 -04:00
|
|
|
object_class->constructed = meta_compositor_constructed;
|
2019-01-11 11:18:27 -05:00
|
|
|
object_class->dispose = meta_compositor_dispose;
|
2019-08-14 17:25:54 -04:00
|
|
|
|
2022-01-28 18:15:28 -05:00
|
|
|
klass->unmanage = meta_compositor_real_unmanage;
|
2019-08-14 17:25:54 -04:00
|
|
|
klass->remove_window = meta_compositor_real_remove_window;
|
2020-05-29 18:02:42 -04:00
|
|
|
klass->before_paint = meta_compositor_real_before_paint;
|
|
|
|
klass->after_paint = meta_compositor_real_after_paint;
|
2019-08-19 04:24:17 -04:00
|
|
|
|
|
|
|
obj_props[PROP_DISPLAY] =
|
|
|
|
g_param_spec_object ("display",
|
|
|
|
"display",
|
|
|
|
"MetaDisplay",
|
|
|
|
META_TYPE_DISPLAY,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2020-04-16 13:14:21 -04:00
|
|
|
obj_props[PROP_BACKEND] =
|
|
|
|
g_param_spec_object ("backend",
|
|
|
|
"backend",
|
|
|
|
"MetaBackend",
|
|
|
|
META_TYPE_BACKEND,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2019-08-19 04:24:17 -04:00
|
|
|
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
2022-07-10 07:44:34 -04:00
|
|
|
|
|
|
|
quark_compositor_view =
|
|
|
|
g_quark_from_static_string ("-meta-compositor-view");
|
2008-06-04 08:58:36 -04:00
|
|
|
}
|
2008-06-06 09:17:38 -04:00
|
|
|
|
2011-08-27 05:43:09 -04:00
|
|
|
/**
|
2017-08-26 15:43:17 -04:00
|
|
|
* meta_disable_unredirect_for_display:
|
|
|
|
* @display: a #MetaDisplay
|
2011-08-27 05:43:09 -04:00
|
|
|
*
|
2020-08-26 05:49:50 -04:00
|
|
|
* Disables unredirection, can be useful in situations where having
|
|
|
|
* unredirected windows is undesirable like when recording a video.
|
2011-08-27 05:43:09 -04:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
void
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_disable_unredirect_for_display (MetaDisplay *display)
|
2011-08-27 05:43:09 -04:00
|
|
|
{
|
2019-09-25 16:23:09 -04:00
|
|
|
MetaCompositor *compositor;
|
|
|
|
MetaCompositorPrivate *priv;
|
|
|
|
|
|
|
|
if (display->closing)
|
|
|
|
return;
|
|
|
|
|
|
|
|
compositor = get_compositor_for_display (display);
|
|
|
|
priv = meta_compositor_get_instance_private (compositor);
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
priv->disable_unredirect_count++;
|
2011-08-27 05:43:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-08-26 15:43:17 -04:00
|
|
|
* meta_enable_unredirect_for_display:
|
|
|
|
* @display: a #MetaDisplay
|
2011-08-27 05:43:09 -04:00
|
|
|
*
|
|
|
|
* Enables unredirection which reduces the overhead for apps like games.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_enable_unredirect_for_display (MetaDisplay *display)
|
2011-08-27 05:43:09 -04:00
|
|
|
{
|
2019-09-25 16:23:09 -04:00
|
|
|
MetaCompositor *compositor;
|
|
|
|
MetaCompositorPrivate *priv;
|
|
|
|
|
|
|
|
if (display->closing)
|
|
|
|
return;
|
|
|
|
|
|
|
|
compositor = get_compositor_for_display (display);
|
|
|
|
priv = meta_compositor_get_instance_private (compositor);
|
2019-08-14 13:04:41 -04:00
|
|
|
|
|
|
|
if (priv->disable_unredirect_count == 0)
|
2017-08-26 15:43:17 -04:00
|
|
|
g_warning ("Called enable_unredirect_for_display while unredirection is enabled.");
|
2019-08-14 13:04:41 -04:00
|
|
|
if (priv->disable_unredirect_count > 0)
|
|
|
|
priv->disable_unredirect_count--;
|
2011-08-27 05:43:09 -04:00
|
|
|
}
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
gboolean
|
|
|
|
meta_compositor_is_unredirect_inhibited (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return priv->disable_unredirect_count > 0;
|
|
|
|
}
|
|
|
|
|
2011-03-18 09:36:28 -04:00
|
|
|
#define FLASH_TIME_MS 50
|
|
|
|
|
|
|
|
static void
|
2012-01-17 09:16:46 -05:00
|
|
|
flash_out_completed (ClutterTimeline *timeline,
|
2013-03-03 18:17:17 -05:00
|
|
|
gboolean is_finished,
|
2012-01-17 09:16:46 -05:00
|
|
|
gpointer user_data)
|
2011-03-18 09:36:28 -04:00
|
|
|
{
|
2012-01-17 09:16:46 -05:00
|
|
|
ClutterActor *flash = CLUTTER_ACTOR (user_data);
|
2011-03-18 09:36:28 -04:00
|
|
|
clutter_actor_destroy (flash);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-08-26 15:43:17 -04:00
|
|
|
meta_compositor_flash_display (MetaCompositor *compositor,
|
|
|
|
MetaDisplay *display)
|
2011-03-18 09:36:28 -04:00
|
|
|
{
|
|
|
|
ClutterActor *stage;
|
|
|
|
ClutterActor *flash;
|
2012-01-17 09:16:46 -05:00
|
|
|
ClutterTransition *transition;
|
2011-03-18 09:36:28 -04:00
|
|
|
gfloat width, height;
|
|
|
|
|
2017-08-26 15:43:17 -04:00
|
|
|
stage = meta_get_stage_for_display (display);
|
2011-03-18 09:36:28 -04:00
|
|
|
clutter_actor_get_size (stage, &width, &height);
|
|
|
|
|
2012-01-17 09:16:46 -05:00
|
|
|
flash = clutter_actor_new ();
|
|
|
|
clutter_actor_set_background_color (flash, CLUTTER_COLOR_Black);
|
2011-03-18 09:36:28 -04:00
|
|
|
clutter_actor_set_size (flash, width, height);
|
|
|
|
clutter_actor_set_opacity (flash, 0);
|
2012-01-17 09:16:46 -05:00
|
|
|
clutter_actor_add_child (stage, flash);
|
|
|
|
|
|
|
|
clutter_actor_save_easing_state (flash);
|
|
|
|
clutter_actor_set_easing_mode (flash, CLUTTER_EASE_IN_QUAD);
|
|
|
|
clutter_actor_set_easing_duration (flash, FLASH_TIME_MS);
|
|
|
|
clutter_actor_set_opacity (flash, 192);
|
|
|
|
|
|
|
|
transition = clutter_actor_get_transition (flash, "opacity");
|
|
|
|
clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE);
|
|
|
|
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 2);
|
|
|
|
|
2013-03-03 18:17:17 -05:00
|
|
|
g_signal_connect (transition, "stopped",
|
2012-01-17 09:16:46 -05:00
|
|
|
G_CALLBACK (flash_out_completed), flash);
|
2011-03-18 09:36:28 -04:00
|
|
|
|
2012-01-17 09:16:46 -05:00
|
|
|
clutter_actor_restore_easing_state (flash);
|
2011-03-18 09:36:28 -04:00
|
|
|
}
|
2012-11-12 14:09:38 -05:00
|
|
|
|
2016-03-07 23:10:21 -05:00
|
|
|
static void
|
|
|
|
window_flash_out_completed (ClutterTimeline *timeline,
|
|
|
|
gboolean is_finished,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
ClutterActor *flash = CLUTTER_ACTOR (user_data);
|
|
|
|
clutter_actor_destroy (flash);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_flash_window (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
|
|
|
ClutterActor *window_actor =
|
2019-07-26 17:03:00 -04:00
|
|
|
CLUTTER_ACTOR (meta_window_actor_from_window (window));
|
2016-03-07 23:10:21 -05:00
|
|
|
ClutterActor *flash;
|
|
|
|
ClutterTransition *transition;
|
|
|
|
|
|
|
|
flash = clutter_actor_new ();
|
|
|
|
clutter_actor_set_background_color (flash, CLUTTER_COLOR_Black);
|
|
|
|
clutter_actor_set_size (flash, window->rect.width, window->rect.height);
|
|
|
|
clutter_actor_set_position (flash,
|
|
|
|
window->custom_frame_extents.left,
|
|
|
|
window->custom_frame_extents.top);
|
|
|
|
clutter_actor_set_opacity (flash, 0);
|
|
|
|
clutter_actor_add_child (window_actor, flash);
|
|
|
|
|
|
|
|
clutter_actor_save_easing_state (flash);
|
|
|
|
clutter_actor_set_easing_mode (flash, CLUTTER_EASE_IN_QUAD);
|
|
|
|
clutter_actor_set_easing_duration (flash, FLASH_TIME_MS);
|
|
|
|
clutter_actor_set_opacity (flash, 192);
|
|
|
|
|
|
|
|
transition = clutter_actor_get_transition (flash, "opacity");
|
|
|
|
clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE);
|
|
|
|
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 2);
|
|
|
|
|
|
|
|
g_signal_connect (transition, "stopped",
|
|
|
|
G_CALLBACK (window_flash_out_completed), flash);
|
|
|
|
|
|
|
|
clutter_actor_restore_easing_state (flash);
|
|
|
|
}
|
|
|
|
|
2012-11-12 14:09:38 -05:00
|
|
|
/**
|
compositor: Make sure _NET_WM_FRAME_DRAWN timestamp has the right scope
The timestamp sent with _NET_WM_FRAME_DRAWN should be in "high
resolution X server timestamps", meaning they should have the same scope
as the built in X11 32 bit unsigned integer timestamps, i.e. overflow at
the same time.
This was not done correctly when mutter had determined the X server used
the monotonic clock, where it'd just forward the monotonic clock,
confusing any client using _NET_WM_FRAME_DRAWN and friends.
Fix this by 1) splitting the timestamp conversiot into an X11 case and a
display server case, where the display server case simply clamps the
monotonic clock, as it is assumed Xwayland is always usign the monotonic
clock, and 2) if we're a X11 compositing manager, if the X server is
using the monotonic clock, apply the same semantics as the display
server case and always just clamp, or if not, calculate the offset every
10 seconds, and offset the monotonic clock timestamp with the calculated
X server timestamp offset.
This fixes an issue that would occur if mutter (or rather GNOME Shell)
would have been started before a X11 timestamp overflow, after the
overflow happened. In this case, GTK3 clients would get unclamped
timestamps, and get very confused, resulting in frames queued several
weeks into the future.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1494
2020-07-08 10:53:14 -04:00
|
|
|
* meta_compositor_monotonic_to_high_res_xserver_time:
|
2012-11-12 14:09:38 -05:00
|
|
|
* @display: a #MetaDisplay
|
|
|
|
* @monotonic_time: time in the units of g_get_monotonic_time()
|
|
|
|
*
|
|
|
|
* _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages represent time
|
|
|
|
* as a "high resolution server time" - this is the server time interpolated
|
|
|
|
* to microsecond resolution. The advantage of this time representation
|
|
|
|
* is that if X server is running on the same computer as a client, and
|
|
|
|
* the Xserver uses 'clock_gettime(CLOCK_MONOTONIC, ...)' for the server
|
|
|
|
* time, the client can detect this, and all such clients will share a
|
|
|
|
* a time representation with high accuracy. If there is not a common
|
|
|
|
* time source, then the time synchronization will be less accurate.
|
|
|
|
*/
|
compositor: Make sure _NET_WM_FRAME_DRAWN timestamp has the right scope
The timestamp sent with _NET_WM_FRAME_DRAWN should be in "high
resolution X server timestamps", meaning they should have the same scope
as the built in X11 32 bit unsigned integer timestamps, i.e. overflow at
the same time.
This was not done correctly when mutter had determined the X server used
the monotonic clock, where it'd just forward the monotonic clock,
confusing any client using _NET_WM_FRAME_DRAWN and friends.
Fix this by 1) splitting the timestamp conversiot into an X11 case and a
display server case, where the display server case simply clamps the
monotonic clock, as it is assumed Xwayland is always usign the monotonic
clock, and 2) if we're a X11 compositing manager, if the X server is
using the monotonic clock, apply the same semantics as the display
server case and always just clamp, or if not, calculate the offset every
10 seconds, and offset the monotonic clock timestamp with the calculated
X server timestamp offset.
This fixes an issue that would occur if mutter (or rather GNOME Shell)
would have been started before a X11 timestamp overflow, after the
overflow happened. In this case, GTK3 clients would get unclamped
timestamps, and get very confused, resulting in frames queued several
weeks into the future.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1494
2020-07-08 10:53:14 -04:00
|
|
|
int64_t
|
|
|
|
meta_compositor_monotonic_to_high_res_xserver_time (MetaCompositor *compositor,
|
|
|
|
int64_t monotonic_time_us)
|
2012-11-12 14:09:38 -05:00
|
|
|
{
|
compositor: Make sure _NET_WM_FRAME_DRAWN timestamp has the right scope
The timestamp sent with _NET_WM_FRAME_DRAWN should be in "high
resolution X server timestamps", meaning they should have the same scope
as the built in X11 32 bit unsigned integer timestamps, i.e. overflow at
the same time.
This was not done correctly when mutter had determined the X server used
the monotonic clock, where it'd just forward the monotonic clock,
confusing any client using _NET_WM_FRAME_DRAWN and friends.
Fix this by 1) splitting the timestamp conversiot into an X11 case and a
display server case, where the display server case simply clamps the
monotonic clock, as it is assumed Xwayland is always usign the monotonic
clock, and 2) if we're a X11 compositing manager, if the X server is
using the monotonic clock, apply the same semantics as the display
server case and always just clamp, or if not, calculate the offset every
10 seconds, and offset the monotonic clock timestamp with the calculated
X server timestamp offset.
This fixes an issue that would occur if mutter (or rather GNOME Shell)
would have been started before a X11 timestamp overflow, after the
overflow happened. In this case, GTK3 clients would get unclamped
timestamps, and get very confused, resulting in frames queued several
weeks into the future.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1494
2020-07-08 10:53:14 -04:00
|
|
|
MetaCompositorClass *klass = META_COMPOSITOR_GET_CLASS (compositor);
|
2012-11-12 14:09:38 -05:00
|
|
|
|
compositor: Make sure _NET_WM_FRAME_DRAWN timestamp has the right scope
The timestamp sent with _NET_WM_FRAME_DRAWN should be in "high
resolution X server timestamps", meaning they should have the same scope
as the built in X11 32 bit unsigned integer timestamps, i.e. overflow at
the same time.
This was not done correctly when mutter had determined the X server used
the monotonic clock, where it'd just forward the monotonic clock,
confusing any client using _NET_WM_FRAME_DRAWN and friends.
Fix this by 1) splitting the timestamp conversiot into an X11 case and a
display server case, where the display server case simply clamps the
monotonic clock, as it is assumed Xwayland is always usign the monotonic
clock, and 2) if we're a X11 compositing manager, if the X server is
using the monotonic clock, apply the same semantics as the display
server case and always just clamp, or if not, calculate the offset every
10 seconds, and offset the monotonic clock timestamp with the calculated
X server timestamp offset.
This fixes an issue that would occur if mutter (or rather GNOME Shell)
would have been started before a X11 timestamp overflow, after the
overflow happened. In this case, GTK3 clients would get unclamped
timestamps, and get very confused, resulting in frames queued several
weeks into the future.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1494
2020-07-08 10:53:14 -04:00
|
|
|
return klass->monotonic_to_high_res_xserver_time (compositor, monotonic_time_us);
|
2012-11-12 14:09:38 -05:00
|
|
|
}
|
2012-03-24 06:29:39 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_show_tile_preview (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaRectangle *tile_rect,
|
|
|
|
int tile_monitor_number)
|
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
meta_plugin_manager_show_tile_preview (priv->plugin_mgr,
|
2012-03-24 06:29:39 -04:00
|
|
|
window, tile_rect, tile_monitor_number);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-03-18 17:31:22 -04:00
|
|
|
meta_compositor_hide_tile_preview (MetaCompositor *compositor)
|
2012-03-24 06:29:39 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
meta_plugin_manager_hide_tile_preview (priv->plugin_mgr);
|
2012-03-24 06:29:39 -04:00
|
|
|
}
|
2014-03-13 18:34:14 -04:00
|
|
|
|
|
|
|
void
|
2014-05-23 17:14:51 -04:00
|
|
|
meta_compositor_show_window_menu (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaWindowMenuType menu,
|
|
|
|
int x,
|
|
|
|
int y)
|
2014-03-13 18:34:14 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
meta_plugin_manager_show_window_menu (priv->plugin_mgr, window, menu, x, y);
|
2014-03-13 18:34:14 -04:00
|
|
|
}
|
2014-05-30 18:52:06 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaWindowMenuType menu,
|
2019-06-13 04:39:31 -04:00
|
|
|
MetaRectangle *rect)
|
2014-05-30 18:52:06 -04:00
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
meta_plugin_manager_show_window_menu_for_rect (priv->plugin_mgr, window, menu, rect);
|
2014-05-30 18:52:06 -04:00
|
|
|
}
|
2017-01-26 13:48:52 -05:00
|
|
|
|
|
|
|
MetaCloseDialog *
|
|
|
|
meta_compositor_create_close_dialog (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return meta_plugin_manager_create_close_dialog (priv->plugin_mgr,
|
2017-01-26 13:48:52 -05:00
|
|
|
window);
|
|
|
|
}
|
2017-06-14 05:20:54 -04:00
|
|
|
|
|
|
|
MetaInhibitShortcutsDialog *
|
|
|
|
meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return meta_plugin_manager_create_inhibit_shortcuts_dialog (priv->plugin_mgr,
|
2017-06-14 05:20:54 -04:00
|
|
|
window);
|
|
|
|
}
|
2019-02-20 05:07:22 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_locate_pointer (MetaCompositor *compositor)
|
|
|
|
{
|
2019-08-14 13:04:41 -04:00
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
meta_plugin_manager_locate_pointer (priv->plugin_mgr);
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaPluginManager *
|
|
|
|
meta_compositor_get_plugin_manager (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return priv->plugin_mgr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaDisplay *
|
|
|
|
meta_compositor_get_display (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return priv->display;
|
|
|
|
}
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
ClutterStage *
|
|
|
|
meta_compositor_get_stage (MetaCompositor *compositor)
|
2019-08-14 13:04:41 -04:00
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
2020-04-16 13:14:21 -04:00
|
|
|
return CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
|
2019-08-14 13:04:41 -04:00
|
|
|
}
|
|
|
|
|
2022-02-05 07:12:48 -05:00
|
|
|
MetaBackend *
|
|
|
|
meta_compositor_get_backend (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return priv->backend;
|
|
|
|
}
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
MetaWindowActor *
|
|
|
|
meta_compositor_get_top_window_actor (MetaCompositor *compositor)
|
2019-08-14 13:04:41 -04:00
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
2019-08-14 17:25:54 -04:00
|
|
|
return priv->top_window_actor;
|
2019-08-14 13:04:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_compositor_is_switching_workspace (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return priv->switch_workspace_in_progress > 0;
|
2019-02-20 05:07:22 -05:00
|
|
|
}
|
2020-03-03 03:32:33 -05:00
|
|
|
|
|
|
|
MetaLaters *
|
|
|
|
meta_compositor_get_laters (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
MetaCompositorPrivate *priv =
|
|
|
|
meta_compositor_get_instance_private (compositor);
|
|
|
|
|
|
|
|
return priv->laters;
|
|
|
|
}
|