[mutter/wayland] Revert unintentional merge from wip/surface-content to wayland
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wayland] Revert unintentional merge from wip/surface-content to wayland
- Date: Wed, 22 Jan 2014 14:18:46 +0000 (UTC)
commit 20545941fabf15c4f3fb96b5143340c484c6a265
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Wed Jan 22 09:16:56 2014 -0500
Revert unintentional merge from wip/surface-content to wayland
This reverts a lot of commits.
doc/reference/meta-sections.txt | 2 +
src/Makefile.am | 4 -
src/compositor/compositor-private.h | 7 +-
src/compositor/compositor.c | 183 +++++--
src/compositor/meta-surface-actor-wayland.c | 159 ------
src/compositor/meta-surface-actor-wayland.h | 65 ---
src/compositor/meta-surface-actor-x11.c | 551 ------------------
src/compositor/meta-surface-actor-x11.h | 69 ---
src/compositor/meta-surface-actor.c | 210 +++-----
src/compositor/meta-surface-actor.h | 48 +-
src/compositor/meta-window-actor-private.h | 11 +-
src/compositor/meta-window-actor.c | 819 ++++++++++++++++++++++-----
src/compositor/meta-window-group.c | 17 +-
src/compositor/plugins/default.c | 2 +-
src/core/display.c | 2 +-
src/core/frame.c | 3 +-
src/core/frame.h | 1 +
src/core/window.c | 240 ++++++---
src/meta/compositor.h | 13 +-
src/meta/meta-window-actor.h | 3 +
src/meta/window.h | 2 +
src/wayland/meta-wayland-surface.c | 17 +-
src/wayland/meta-xwayland.c | 2 -
23 files changed, 1129 insertions(+), 1301 deletions(-)
---
diff --git a/doc/reference/meta-sections.txt b/doc/reference/meta-sections.txt
index 22d4350..7aa8931 100644
--- a/doc/reference/meta-sections.txt
+++ b/doc/reference/meta-sections.txt
@@ -96,6 +96,8 @@ meta_compositor_hide_window
meta_compositor_switch_workspace
meta_compositor_maximize_window
meta_compositor_unmaximize_window
+meta_compositor_window_mapped
+meta_compositor_window_unmapped
meta_compositor_sync_window_geometry
meta_compositor_set_updates_frozen
meta_compositor_queue_frame_drawn
diff --git a/src/Makefile.am b/src/Makefile.am
index 991c1ae..b81c6ec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,10 +83,6 @@ libmutter_wayland_la_SOURCES = \
compositor/meta-shaped-texture-private.h \
compositor/meta-surface-actor.c \
compositor/meta-surface-actor.h \
- compositor/meta-surface-actor-x11.c \
- compositor/meta-surface-actor-x11.h \
- compositor/meta-surface-actor-wayland.c \
- compositor/meta-surface-actor-wayland.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 18bcff6..2e8d85f 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -46,8 +46,11 @@ struct _MetaCompScreen
CoglFrameClosure *frame_closure;
/* Used for unredirecting fullscreen windows */
- guint disable_unredirect_count;
- MetaWindow *unredirected_window;
+ guint disable_unredirect_count;
+ MetaWindowActor *unredirected_window;
+
+ /* Before we create the output window */
+ XserverRegion pending_input_region;
gint switch_workspace_in_progress;
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 0fb8df9..d2598f4 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -42,6 +42,15 @@
* the call, so it may be necessary to readjust the display based on the
* old_rect to start the animation.
*
+ * meta_compositor_window_mapped() and meta_compositor_window_unmapped() are
+ * notifications when the toplevel window (frame or client window) is mapped or
+ * unmapped. That is, when the result of meta_window_toplevel_is_mapped()
+ * changes. The main use of this is to drop resources when a window is unmapped.
+ * A window will always be mapped before meta_compositor_show_window()
+ * is called and will not be unmapped until after meta_compositor_hide_window()
+ * is called. If the live_hidden_windows preference is set, windows will never
+ * be unmapped.
+ *
* # Containers #
*
* There's two containers in the stage that are used to place window actors, here
@@ -274,6 +283,25 @@ meta_get_window_actors (MetaScreen *screen)
return info->windows;
}
+static void
+do_set_stage_input_region (MetaScreen *screen,
+ XserverRegion region)
+{
+ MetaCompScreen *info = meta_screen_get_compositor_data (screen);
+ MetaDisplay *display = meta_screen_get_display (screen);
+ Display *xdpy = meta_display_get_xdisplay (display);
+ Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
+
+ XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
+
+ /* It's generally a good heuristic that when a crossing event is generated because
+ * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
+ * it's not the user doing something, it's the environment changing under the user.
+ */
+ meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
+ XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
+}
+
void
meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
@@ -285,19 +313,29 @@ meta_set_stage_input_region (MetaScreen *screen,
*/
if (!meta_is_wayland_compositor ())
{
- MetaCompScreen *info = meta_screen_get_compositor_data (screen);
- MetaDisplay *display = meta_screen_get_display (screen);
- Display *xdpy = meta_display_get_xdisplay (display);
- Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
-
- XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
+ MetaCompScreen *info = meta_screen_get_compositor_data (screen);
+ MetaDisplay *display = meta_screen_get_display (screen);
+ Display *xdpy = meta_display_get_xdisplay (display);
- /* It's generally a good heuristic that when a crossing event is generated because
- * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
- * it's not the user doing something, it's the environment changing under the user.
- */
- meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
- XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
+ if (info->stage && info->output)
+ {
+ do_set_stage_input_region (screen, region);
+ }
+ else
+ {
+ /* Reset info->pending_input_region if one existed before and set the new
+ * one to use it later. */
+ if (info->pending_input_region)
+ {
+ XFixesDestroyRegion (xdpy, info->pending_input_region);
+ info->pending_input_region = None;
+ }
+ if (region != None)
+ {
+ info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
+ XFixesCopyRegion (xdpy, info->pending_input_region, region);
+ }
+ }
}
}
@@ -639,6 +677,21 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
return;
info = g_new0 (MetaCompScreen, 1);
+ /*
+ * We use an empty input region for Clutter as a default because that allows
+ * the user to interact with all the windows displayed on the screen.
+ * We have to initialize info->pending_input_region to an empty region explicitly,
+ * because None value is used to mean that the whole screen is an input region.
+ */
+ if (!meta_is_wayland_compositor ())
+ info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);
+ else
+ {
+ /* Stage input region trickery isn't needed when we're running as a
+ * wayland compositor. */
+ info->pending_input_region = None;
+ }
+
info->screen = screen;
meta_screen_set_compositor_data (screen, info);
@@ -724,8 +777,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
info->output = get_output_window (screen);
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
- meta_empty_stage_input_region (screen);
-
/* Make sure there isn't any left-over output shape on the
* overlay window by setting the whole screen to be an
* output region.
@@ -736,6 +787,13 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
*/
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
+ do_set_stage_input_region (screen, info->pending_input_region);
+ if (info->pending_input_region != None)
+ {
+ XFixesDestroyRegion (xdisplay, info->pending_input_region);
+ info->pending_input_region = None;
+ }
+
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
@@ -805,30 +863,6 @@ meta_shape_cow_for_window (MetaScreen *screen,
}
}
-static void
-set_unredirected_window (MetaCompScreen *info,
- MetaWindow *window)
-{
- if (info->unredirected_window == window)
- return;
-
- if (info->unredirected_window != NULL)
- {
- MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private
(info->unredirected_window));
- meta_window_actor_set_unredirected (window_actor, FALSE);
- }
-
- info->unredirected_window = window;
-
- if (info->unredirected_window != NULL)
- {
- MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private
(info->unredirected_window));
- meta_window_actor_set_unredirected (window_actor, TRUE);
- }
-
- meta_shape_cow_for_window (info->screen, info->unredirected_window);
-}
-
void
meta_compositor_add_window (MetaCompositor *compositor,
MetaWindow *window)
@@ -857,11 +891,19 @@ meta_compositor_remove_window (MetaCompositor *compositor,
if (!window_actor)
return;
- screen = meta_window_get_screen (window);
- info = meta_screen_get_compositor_data (screen);
+ if (!meta_is_wayland_compositor ())
+ {
+ screen = meta_window_get_screen (window);
+ info = meta_screen_get_compositor_data (screen);
- if (info->unredirected_window == window)
- set_unredirected_window (info, NULL);
+ if (window_actor == info->unredirected_window)
+ {
+ meta_window_actor_set_redirected (window_actor, TRUE);
+ meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window
(info->unredirected_window)),
+ NULL);
+ info->unredirected_window = NULL;
+ }
+ }
meta_window_actor_destroy (window_actor);
}
@@ -1361,6 +1403,30 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
}
void
+meta_compositor_window_mapped (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+ MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
+ DEBUG_TRACE ("meta_compositor_window_mapped\n");
+ if (!window_actor)
+ return;
+
+ meta_window_actor_mapped (window_actor);
+}
+
+void
+meta_compositor_window_unmapped (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+ MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
+ DEBUG_TRACE ("meta_compositor_window_unmapped\n");
+ if (!window_actor)
+ return;
+
+ meta_window_actor_unmapped (window_actor);
+}
+
+void
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
gboolean did_placement)
@@ -1467,6 +1533,7 @@ pre_paint_windows (MetaCompScreen *info)
{
GList *l;
MetaWindowActor *top_window;
+ MetaWindowActor *expected_unredirected_window = NULL;
if (info->onscreen == NULL)
{
@@ -1480,13 +1547,33 @@ pre_paint_windows (MetaCompScreen *info)
if (info->windows == NULL)
return;
- top_window = g_list_last (info->windows)->data;
+ if (!meta_is_wayland_compositor ())
+ {
+ top_window = g_list_last (info->windows)->data;
- if (meta_window_actor_should_unredirect (top_window) &&
- info->disable_unredirect_count == 0)
- set_unredirected_window (info, meta_window_actor_get_meta_window (top_window));
- else
- set_unredirected_window (info, NULL);
+ if (meta_window_actor_should_unredirect (top_window) &&
+ info->disable_unredirect_count == 0)
+ expected_unredirected_window = top_window;
+
+ if (info->unredirected_window != expected_unredirected_window)
+ {
+ if (info->unredirected_window != NULL)
+ {
+ meta_window_actor_set_redirected (info->unredirected_window, TRUE);
+ meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window
(info->unredirected_window)),
+ NULL);
+ }
+
+ if (expected_unredirected_window != NULL)
+ {
+ meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window
(top_window)),
+ meta_window_actor_get_meta_window (top_window));
+ meta_window_actor_set_redirected (top_window, FALSE);
+ }
+
+ info->unredirected_window = expected_unredirected_window;
+ }
+ }
for (l = info->windows; l; l = l->next)
meta_window_actor_pre_paint (l->data);
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index 9d21c74..37b87b0 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -10,118 +10,44 @@
*/
#include <config.h>
-
-#include "meta-surface-actor.h"
-
#include <clutter/clutter.h>
+#include <cogl/cogl-wayland-server.h>
+#include <cogl/cogl-texture-pixmap-x11.h>
#include <meta/meta-shaped-texture.h>
+#include "meta-surface-actor.h"
#include "meta-wayland-private.h"
#include "meta-cullable.h"
+
#include "meta-shaped-texture-private.h"
struct _MetaSurfaceActorPrivate
{
MetaShapedTexture *texture;
-
- /* The region that is visible, used to optimize out redraws */
- cairo_region_t *unobscured_region;
+ MetaWaylandBuffer *buffer;
};
static void cullable_iface_init (MetaCullableInterface *iface);
-G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
- G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
-
-static gboolean
-meta_surface_actor_get_paint_volume (ClutterActor *actor,
- ClutterPaintVolume *volume)
-{
- MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
- MetaSurfaceActorPrivate *priv = self->priv;
-
- if (!CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->get_paint_volume (actor, volume))
- return FALSE;
-
- if (priv->unobscured_region)
- {
- ClutterVertex origin;
- cairo_rectangle_int_t bounds, unobscured_bounds;
-
- /* I hate ClutterPaintVolume so much... */
- clutter_paint_volume_get_origin (volume, &origin);
- bounds.x = origin.x;
- bounds.y = origin.y;
- bounds.width = clutter_paint_volume_get_width (volume);
- bounds.height = clutter_paint_volume_get_height (volume);
-
- cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds);
- gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
-
- origin.x = bounds.x;
- origin.y = bounds.y;
- clutter_paint_volume_set_origin (volume, &origin);
- clutter_paint_volume_set_width (volume, bounds.width);
- clutter_paint_volume_set_height (volume, bounds.height);
- }
-
- return TRUE;
-}
-
-static void
-meta_surface_actor_dispose (GObject *object)
-{
- MetaSurfaceActor *self = META_SURFACE_ACTOR (object);
- MetaSurfaceActorPrivate *priv = self->priv;
-
- g_clear_pointer (&priv->unobscured_region, cairo_region_destroy);
-
- G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
-}
+G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
+ G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
{
- ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- actor_class->get_paint_volume = meta_surface_actor_get_paint_volume;
- object_class->dispose = meta_surface_actor_dispose;
-
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
}
static void
-set_unobscured_region (MetaSurfaceActor *self,
- cairo_region_t *unobscured_region)
-{
- MetaSurfaceActorPrivate *priv = self->priv;
-
- if (priv->unobscured_region)
- cairo_region_destroy (priv->unobscured_region);
-
- if (unobscured_region)
- priv->unobscured_region = cairo_region_copy (unobscured_region);
- else
- priv->unobscured_region = NULL;
-}
-
-static void
meta_surface_actor_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
- MetaSurfaceActor *self = META_SURFACE_ACTOR (cullable);
-
- set_unobscured_region (self, unobscured_region);
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
}
static void
meta_surface_actor_reset_culling (MetaCullable *cullable)
{
- MetaSurfaceActor *self = META_SURFACE_ACTOR (cullable);
-
- set_unobscured_region (self, NULL);
meta_cullable_reset_culling_children (cullable);
}
@@ -158,104 +84,100 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
return self->priv->texture;
}
-static cairo_region_t *
-effective_unobscured_region (MetaSurfaceActor *self)
+static void
+update_area (MetaSurfaceActor *self,
+ int x, int y, int width, int height)
{
MetaSurfaceActorPrivate *priv = self->priv;
- return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region;
+ if (meta_is_wayland_compositor ())
+ {
+ struct wl_resource *resource = priv->buffer->resource;
+ struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
+
+ if (shm_buffer)
+ {
+ CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
+ cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y,
0, NULL);
+ }
+ }
+ else
+ {
+ CoglTexturePixmapX11 *texture = COGL_TEXTURE_PIXMAP_X11 (meta_shaped_texture_get_texture
(priv->texture));
+ cogl_texture_pixmap_x11_update_area (texture, x, y, width, height);
+ }
}
gboolean
-meta_surface_actor_redraw_area (MetaSurfaceActor *self,
- int x, int y, int width, int height)
+meta_surface_actor_damage_all (MetaSurfaceActor *self,
+ cairo_region_t *unobscured_region)
{
MetaSurfaceActorPrivate *priv = self->priv;
+ CoglTexture *texture = meta_shaped_texture_get_texture (priv->texture);
+ update_area (self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
return meta_shaped_texture_update_area (priv->texture,
- x, y, width, height,
- effective_unobscured_region (self));
+ 0, 0,
+ cogl_texture_get_width (texture),
+ cogl_texture_get_height (texture),
+ unobscured_region);
}
gboolean
-meta_surface_actor_is_obscured (MetaSurfaceActor *self)
+meta_surface_actor_damage_area (MetaSurfaceActor *self,
+ int x,
+ int y,
+ int width,
+ int height,
+ cairo_region_t *unobscured_region)
{
MetaSurfaceActorPrivate *priv = self->priv;
- if (priv->unobscured_region)
- return cairo_region_is_empty (priv->unobscured_region);
- else
- return FALSE;
-}
-
-void
-meta_surface_actor_set_input_region (MetaSurfaceActor *self,
- cairo_region_t *region)
-{
- MetaSurfaceActorPrivate *priv = self->priv;
- meta_shaped_texture_set_input_shape_region (priv->texture, region);
+ update_area (self, x, y, width, height);
+ return meta_shaped_texture_update_area (priv->texture,
+ x, y, width, height,
+ unobscured_region);
}
void
-meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
- cairo_region_t *region)
+meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
+ MetaWaylandBuffer *buffer)
{
MetaSurfaceActorPrivate *priv = self->priv;
- meta_shaped_texture_set_opaque_region (priv->texture, region);
-}
+ priv->buffer = buffer;
-void
-meta_surface_actor_process_damage (MetaSurfaceActor *actor,
- int x, int y, int width, int height)
-{
- META_SURFACE_ACTOR_GET_CLASS (actor)->process_damage (actor, x, y, width, height);
+ if (buffer)
+ meta_shaped_texture_set_texture (priv->texture, buffer->texture);
+ else
+ meta_shaped_texture_set_texture (priv->texture, NULL);
}
void
-meta_surface_actor_pre_paint (MetaSurfaceActor *actor)
-{
- META_SURFACE_ACTOR_GET_CLASS (actor)->pre_paint (actor);
-}
-
-gboolean
-meta_surface_actor_is_argb32 (MetaSurfaceActor *actor)
+meta_surface_actor_set_texture (MetaSurfaceActor *self,
+ CoglTexture *texture)
{
- return META_SURFACE_ACTOR_GET_CLASS (actor)->is_argb32 (actor);
-}
-
-gboolean
-meta_surface_actor_is_visible (MetaSurfaceActor *actor)
-{
- return META_SURFACE_ACTOR_GET_CLASS (actor)->is_visible (actor);
+ MetaSurfaceActorPrivate *priv = self->priv;
+ meta_shaped_texture_set_texture (priv->texture, texture);
}
void
-meta_surface_actor_freeze (MetaSurfaceActor *actor)
+meta_surface_actor_set_input_region (MetaSurfaceActor *self,
+ cairo_region_t *region)
{
- META_SURFACE_ACTOR_GET_CLASS (actor)->freeze (actor);
+ MetaSurfaceActorPrivate *priv = self->priv;
+ meta_shaped_texture_set_input_shape_region (priv->texture, region);
}
void
-meta_surface_actor_thaw (MetaSurfaceActor *actor)
-{
- META_SURFACE_ACTOR_GET_CLASS (actor)->thaw (actor);
-}
-
-gboolean
-meta_surface_actor_is_frozen (MetaSurfaceActor *actor)
-{
- return META_SURFACE_ACTOR_GET_CLASS (actor)->is_frozen (actor);
-}
-
-gboolean
-meta_surface_actor_should_unredirect (MetaSurfaceActor *actor)
+meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
+ cairo_region_t *region)
{
- return META_SURFACE_ACTOR_GET_CLASS (actor)->should_unredirect (actor);
+ MetaSurfaceActorPrivate *priv = self->priv;
+ meta_shaped_texture_set_opaque_region (priv->texture, region);
}
-void
-meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
- gboolean unredirected)
+MetaSurfaceActor *
+meta_surface_actor_new (void)
{
- META_SURFACE_ACTOR_GET_CLASS (actor)->set_unredirected (actor, unredirected);
+ return g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
}
diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h
index f9d458c..484877b 100644
--- a/src/compositor/meta-surface-actor.h
+++ b/src/compositor/meta-surface-actor.h
@@ -6,6 +6,7 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
+#include "meta-wayland-types.h"
G_BEGIN_DECLS
@@ -24,20 +25,6 @@ struct _MetaSurfaceActorClass
{
/*< private >*/
ClutterActorClass parent_class;
-
- void (* process_damage) (MetaSurfaceActor *actor,
- int x, int y, int width, int height);
- void (* pre_paint) (MetaSurfaceActor *actor);
- gboolean (* is_argb32) (MetaSurfaceActor *actor);
- gboolean (* is_visible) (MetaSurfaceActor *actor);
-
- void (* freeze) (MetaSurfaceActor *actor);
- void (* thaw) (MetaSurfaceActor *actor);
- gboolean (* is_frozen) (MetaSurfaceActor *actor);
-
- gboolean (* should_unredirect) (MetaSurfaceActor *actor);
- void (* set_unredirected) (MetaSurfaceActor *actor,
- gboolean unredirected);
};
struct _MetaSurfaceActor
@@ -49,35 +36,32 @@ struct _MetaSurfaceActor
GType meta_surface_actor_get_type (void);
+MetaSurfaceActor *meta_surface_actor_new (void);
+
cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
cairo_rectangle_int_t *clip);
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
-gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
+gboolean meta_surface_actor_damage_all (MetaSurfaceActor *self,
+ cairo_region_t *unobscured_region);
+
+gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self,
+ int x,
+ int y,
+ int width,
+ int height,
+ cairo_region_t *unobscured_region);
+void meta_surface_actor_set_texture (MetaSurfaceActor *self,
+ CoglTexture *texture);
+void meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
+ MetaWaylandBuffer *buffer);
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
cairo_region_t *region);
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
cairo_region_t *region);
-gboolean meta_surface_actor_redraw_area (MetaSurfaceActor *actor,
- int x, int y, int width, int height);
-
-void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
- int x, int y, int width, int height);
-void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
-gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
-gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
-
-void meta_surface_actor_freeze (MetaSurfaceActor *actor);
-void meta_surface_actor_thaw (MetaSurfaceActor *actor);
-gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor);
-
-gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
-void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
- gboolean unredirected);
-
G_END_DECLS
#endif /* META_SURFACE_ACTOR_PRIVATE_H */
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
index 9c6a847..82326d2 100644
--- a/src/compositor/meta-window-actor-private.h
+++ b/src/compositor/meta-window-actor-private.h
@@ -39,13 +39,13 @@ void meta_window_actor_frame_complete (MetaWindowActor *self,
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
+void meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state);
+
+gboolean meta_window_actor_should_unredirect (MetaWindowActor *self);
+
void meta_window_actor_get_shape_bounds (MetaWindowActor *self,
cairo_rectangle_int_t *bounds);
-gboolean meta_window_actor_should_unredirect (MetaWindowActor *self);
-void meta_window_actor_set_unredirected (MetaWindowActor *self,
- gboolean unredirected);
-
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
void meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
gboolean did_placement);
@@ -59,6 +59,9 @@ void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);
+void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
+ cairo_region_t *unobscured_region);
+
void meta_window_actor_effect_completed (MetaWindowActor *actor,
gulong event);
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 4745d96..e7a9220 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -10,6 +10,10 @@
#include <math.h>
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/Xrender.h>
+
#include <clutter/x11/clutter-x11.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <gdk/gdk.h> /* for gdk_rectangle_union() */
@@ -26,14 +30,21 @@
#include "meta-shaped-texture-private.h"
#include "meta-shadow-factory-private.h"
#include "meta-window-actor-private.h"
+#include "meta-surface-actor.h"
#include "meta-texture-rectangle.h"
#include "region-utils.h"
#include "meta-wayland-private.h"
#include "monitor-private.h"
#include "meta-cullable.h"
-#include "meta-surface-actor.h"
-#include "meta-surface-actor-x11.h"
+enum {
+ POSITION_CHANGED,
+ SIZE_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
struct _MetaWindowActorPrivate
{
@@ -61,13 +72,22 @@ struct _MetaWindowActorPrivate
/* The region we should clip to when painting the shadow */
cairo_region_t *shadow_clip;
- /* Extracted size-invariant shape used for shadows */
- MetaWindowShape *shadow_shape;
- char * shadow_class;
+ /* The region that is visible, used to optimize out redraws */
+ cairo_region_t *unobscured_region;
guint send_frame_messages_timer;
gint64 frame_drawn_time;
+ /* Extracted size-invariant shape used for shadows */
+ MetaWindowShape *shadow_shape;
+
+ gint last_width;
+ gint last_height;
+
+ gint freeze_count;
+
+ char * shadow_class;
+
/*
* These need to be counters rather than flags, since more plugins
* can implement same effect; the practicality of stacking effects
@@ -82,7 +102,12 @@ struct _MetaWindowActorPrivate
/* List of FrameData for recent frames */
GList *frames;
+ Pixmap back_pixmap; /* Not used in wayland compositor mode */
+ Damage damage; /* Not used in wayland compositor mode */
+
guint visible : 1;
+ guint mapped : 1;
+ guint argb32 : 1;
guint disposed : 1;
guint redecorating : 1;
@@ -99,7 +124,24 @@ struct _MetaWindowActorPrivate
guint no_shadow : 1;
+
+ /*
+ * None of these are used in wayland compositor mode...
+ */
+
+ guint needs_damage_all : 1;
+ guint received_x11_damage : 1;
+
+ guint needs_pixmap : 1;
+
+ guint x11_size_changed : 1;
guint updates_frozen : 1;
+
+ guint unredirected : 1;
+
+ /* This is used to detect fullscreen windows that need to be unredirected */
+ guint full_damage_frames_count;
+ guint does_full_damage : 1;
};
typedef struct _FrameData FrameData;
@@ -136,6 +178,7 @@ static gboolean meta_window_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume);
+static void meta_window_actor_detach_x11_pixmap (MetaWindowActor *self);
static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
static void meta_window_actor_handle_updates (MetaWindowActor *self);
@@ -206,6 +249,19 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
g_object_class_install_property (object_class,
PROP_SHADOW_CLASS,
pspec);
+
+ signals[POSITION_CHANGED] =
+ g_signal_new ("position-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+ signals[SIZE_CHANGED] =
+ g_signal_new ("size-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
}
static void
@@ -226,6 +282,9 @@ window_decorated_notify (MetaWindow *mw,
{
MetaWindowActor *self = META_WINDOW_ACTOR (data);
MetaWindowActorPrivate *priv = self->priv;
+ MetaScreen *screen = priv->screen;
+ MetaDisplay *display = meta_screen_get_display (screen);
+ Display *xdisplay = meta_display_get_xdisplay (display);
/*
* Basically, we have to reconstruct the the internals of this object
@@ -233,6 +292,23 @@ window_decorated_notify (MetaWindow *mw,
*/
priv->redecorating = TRUE;
+ if (!meta_is_wayland_compositor ())
+ {
+ meta_window_actor_detach_x11_pixmap (self);
+
+ /*
+ * First of all, clean up any resources we are currently using and will
+ * be replacing.
+ */
+ if (priv->damage != None)
+ {
+ meta_error_trap_push (display);
+ XDamageDestroy (xdisplay, priv->damage);
+ meta_error_trap_pop (display);
+ priv->damage = None;
+ }
+ }
+
/*
* Recreate the contents.
*/
@@ -255,13 +331,8 @@ surface_allocation_changed_notify (ClutterActor *actor,
{
meta_window_actor_sync_actor_geometry (self, FALSE);
meta_window_actor_update_shape (self);
-}
-static gboolean
-is_argb32 (MetaWindowActor *self)
-{
- MetaWindowActorPrivate *priv = self->priv;
- return meta_surface_actor_is_argb32 (priv->surface);
+ g_signal_emit (self, signals[SIZE_CHANGED], 0);
}
static gboolean
@@ -270,96 +341,56 @@ is_non_opaque (MetaWindowActor *self)
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
- return is_argb32 (self) || (window->opacity != 0xFF);
-}
-
-static gboolean
-is_frozen (MetaWindowActor *self)
-{
- MetaWindowActorPrivate *priv = self->priv;
- return meta_surface_actor_is_frozen (priv->surface);
+ return priv->argb32 || (window->opacity != 0xFF);
}
static void
-meta_window_actor_freeze (MetaWindowActor *self)
-{
- MetaWindowActorPrivate *priv = self->priv;
- meta_surface_actor_freeze (priv->surface);
-}
-
-static void
-meta_window_actor_thaw (MetaWindowActor *self)
+meta_window_actor_constructed (GObject *object)
{
- MetaWindowActorPrivate *priv = self->priv;
-
- meta_surface_actor_thaw (priv->surface);
+ MetaWindowActor *self = META_WINDOW_ACTOR (object);
+ MetaWindowActorPrivate *priv = self->priv;
+ MetaWindow *window = priv->window;
+ Window xwindow = meta_window_get_toplevel_xwindow (window);
+ MetaScreen *screen = meta_window_get_screen (window);
+ MetaDisplay *display = meta_screen_get_display (screen);
+ Display *xdisplay = meta_display_get_xdisplay (display);
- if (meta_surface_actor_is_frozen (priv->surface))
- return;
+ priv->screen = screen;
- /* We sometimes ignore moves and resizes on frozen windows */
- meta_window_actor_sync_actor_geometry (self, FALSE);
+ if (!meta_is_wayland_compositor ())
+ priv->damage = XDamageCreate (xdisplay, xwindow,
+ XDamageReportBoundingBox);
- /* We do this now since we might be going right back into the
- * frozen state */
- meta_window_actor_handle_updates (self);
-}
+ if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+ {
+ XRenderPictFormat *format;
-static void
-set_surface_actor (MetaWindowActor *self,
- MetaSurfaceActor *surface)
-{
- MetaWindowActorPrivate *priv = self->priv;
+ format = XRenderFindVisualFormat (xdisplay, window->xvisual);
- if (priv->surface)
+ if (format && format->type == PictTypeDirect && format->direct.alphaMask)
+ priv->argb32 = TRUE;
+ }
+ else
{
- g_object_unref (priv->surface);
- clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
+ /* XXX: parse shm formats to determine argb32 */
+ priv->argb32 = TRUE;
}
- priv->surface = surface;
-
- if (priv->surface)
+ if (!priv->surface)
{
+ if (window->surface)
+ priv->surface = window->surface->surface_actor;
+ else
+ priv->surface = meta_surface_actor_new ();
g_object_ref_sink (priv->surface);
+
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
g_signal_connect_object (priv->surface, "allocation-changed",
G_CALLBACK (surface_allocation_changed_notify), self, 0);
+ meta_window_actor_update_shape (self);
}
- meta_window_actor_update_shape (self);
-}
-
-static void
-meta_window_actor_sync_surface_actor (MetaWindowActor *self)
-{
- MetaWindowActorPrivate *priv = self->priv;
- MetaWindow *window = priv->window;
-
- MetaSurfaceActor *surface = NULL;
-
- if (window)
- {
- if (window->surface)
- surface = window->surface->surface_actor;
- else if (!meta_is_wayland_compositor ())
- surface = meta_surface_actor_x11_new (window);
- }
-
- set_surface_actor (self, surface);
-}
-
-static void
-meta_window_actor_constructed (GObject *object)
-{
- MetaWindowActor *self = META_WINDOW_ACTOR (object);
- MetaWindowActorPrivate *priv = self->priv;
- MetaWindow *window = priv->window;
-
- priv->screen = window->screen;
-
- meta_window_actor_sync_surface_actor (self);
meta_window_actor_update_opacity (self);
/* Start off with an empty shape region to maintain the invariant
@@ -373,6 +404,8 @@ meta_window_actor_dispose (GObject *object)
MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen;
+ MetaDisplay *display;
+ Display *xdisplay;
MetaCompScreen *info;
if (priv->disposed)
@@ -383,12 +416,16 @@ meta_window_actor_dispose (GObject *object)
screen = priv->screen;
info = meta_screen_get_compositor_data (screen);
+ if (!meta_is_wayland_compositor ())
+ meta_window_actor_detach_x11_pixmap (self);
+
if (priv->send_frame_messages_timer != 0)
{
g_source_remove (priv->send_frame_messages_timer);
priv->send_frame_messages_timer = 0;
}
+ g_clear_pointer (&priv->unobscured_region, cairo_region_destroy);
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
@@ -397,11 +434,26 @@ meta_window_actor_dispose (GObject *object)
g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
+ if (!meta_is_wayland_compositor () && priv->damage != None)
+ {
+ display = meta_screen_get_display (screen);
+ xdisplay = meta_display_get_xdisplay (display);
+
+ meta_error_trap_push (display);
+ XDamageDestroy (xdisplay, priv->damage);
+ meta_error_trap_pop (display);
+
+ priv->damage = None;
+ }
+
info->windows = g_list_remove (info->windows, (gconstpointer) self);
g_clear_object (&priv->window);
- meta_window_actor_sync_surface_actor (self);
+ /*
+ * Release the extra reference we took on the actor.
+ */
+ g_clear_object (&priv->surface);
G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
}
@@ -669,15 +721,12 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
}
- {
- const ClutterPaintVolume *child_volume;
-
- child_volume = clutter_actor_get_transformed_paint_volume (CLUTTER_ACTOR (priv->surface), actor);
- if (!child_volume)
- return FALSE;
-
- clutter_paint_volume_union (volume, child_volume);
- }
+ if (priv->unobscured_region)
+ {
+ cairo_rectangle_int_t unobscured_bounds;
+ cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds);
+ gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
+ }
origin.x = bounds.x;
origin.y = bounds.y;
@@ -811,6 +860,66 @@ meta_window_actor_is_destroyed (MetaWindowActor *self)
return self->priv->disposed;
}
+gboolean
+meta_window_actor_is_override_redirect (MetaWindowActor *self)
+{
+ return meta_window_is_override_redirect (self->priv->window);
+}
+
+/**
+ * meta_window_actor_get_workspace:
+ * @self: #MetaWindowActor
+ *
+ * Returns the index of workspace on which this window is located; if the
+ * window is sticky, or is not currently located on any workspace, returns -1.
+ * This function is deprecated and should not be used in newly written code;
+ * meta_window_get_workspace() instead.
+ *
+ * Return value: (transfer none): index of workspace on which this window is
+ * located.
+ */
+gint
+meta_window_actor_get_workspace (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv;
+ MetaWorkspace *workspace;
+
+ if (!self)
+ return -1;
+
+ priv = self->priv;
+
+ if (!priv->window || meta_window_is_on_all_workspaces (priv->window))
+ return -1;
+
+ workspace = meta_window_get_workspace (priv->window);
+
+ if (!workspace)
+ return -1;
+
+ return meta_workspace_index (workspace);
+}
+
+gboolean
+meta_window_actor_showing_on_its_workspace (MetaWindowActor *self)
+{
+ if (!self)
+ return FALSE;
+
+ /* If override redirect: */
+ if (!self->priv->window)
+ return TRUE;
+
+ return meta_window_showing_on_its_workspace (self->priv->window);
+}
+
+static void
+meta_window_actor_freeze (MetaWindowActor *self)
+{
+ if (!meta_is_wayland_compositor ())
+ self->priv->freeze_count++;
+}
+
static gboolean
send_frame_messages_timeout (gpointer data)
{
@@ -865,6 +974,61 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset,
send_frame_messages_timeout, self, NULL);
}
+static void
+meta_window_actor_damage_all (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+ cairo_region_t *unobscured_region;
+ gboolean redraw_queued;
+
+ if (!priv->needs_damage_all)
+ return;
+
+ if (!priv->mapped || priv->needs_pixmap)
+ return;
+
+ unobscured_region =
+ clutter_actor_has_mapped_clones (CLUTTER_ACTOR (priv->surface))
+ ? NULL : priv->unobscured_region;
+
+ redraw_queued = meta_surface_actor_damage_all (priv->surface, unobscured_region);
+
+ priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
+ priv->needs_damage_all = FALSE;
+}
+
+static void
+meta_window_actor_thaw (MetaWindowActor *self)
+{
+ if (!meta_is_wayland_compositor ())
+ {
+ self->priv->freeze_count--;
+
+ if (G_UNLIKELY (self->priv->freeze_count < 0))
+ {
+ g_warning ("Error in freeze/thaw accounting.");
+ self->priv->freeze_count = 0;
+ return;
+ }
+
+ if (self->priv->freeze_count)
+ return;
+
+ /* We sometimes ignore moves and resizes on frozen windows */
+ meta_window_actor_sync_actor_geometry (self, FALSE);
+
+ /* We do this now since we might be going right back into the
+ * frozen state */
+ meta_window_actor_handle_updates (self);
+
+ /* Since we ignore damage events while a window is frozen for certain effects
+ * we may need to issue an update_area() covering the whole pixmap if we
+ * don't know what real damage has happened. */
+ if (self->priv->needs_damage_all)
+ meta_window_actor_damage_all (self);
+ }
+}
+
void
meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame)
@@ -886,7 +1050,17 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
if (!priv->repaint_scheduled)
{
- gboolean is_obscured = meta_surface_actor_is_obscured (priv->surface);
+ gboolean is_obscured = FALSE;
+
+ /* Find out whether the window is completly obscured */
+ if (priv->unobscured_region)
+ {
+ cairo_region_t *unobscured_window_region;
+ unobscured_window_region = cairo_region_copy (priv->shape_region);
+ cairo_region_intersect (unobscured_window_region, priv->unobscured_region);
+ is_obscured = cairo_region_is_empty (unobscured_window_region);
+ cairo_region_destroy (unobscured_window_region);
+ }
/* A frame was marked by the client without actually doing any
* damage or any unobscured, or while we had the window frozen
@@ -900,7 +1074,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
{
queue_send_frame_messages_timeout (self);
}
- else
+ else if (priv->mapped && (!meta_is_wayland_compositor () || !priv->needs_pixmap))
{
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
@@ -920,6 +1094,36 @@ meta_window_actor_effect_in_progress (MetaWindowActor *self)
}
static gboolean
+is_frozen (MetaWindowActor *self)
+{
+ return self->priv->freeze_count ? TRUE : FALSE;
+}
+
+static void
+meta_window_actor_queue_create_x11_pixmap (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+
+ priv->needs_pixmap = TRUE;
+
+ if (!priv->mapped)
+ return;
+
+ if (is_frozen (self))
+ return;
+
+ /* This will cause the compositor paint function to be run
+ * if the actor is visible or a clone of the actor is visible.
+ * if the actor isn't visible in any way, then we don't
+ * need to repair the window anyways, and can wait until
+ * the stage is redrawn for some other reason
+ *
+ * The compositor paint function repairs all windows.
+ */
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
+}
+
+static gboolean
is_freeze_thaw_effect (gulong event)
{
switch (event)
@@ -999,6 +1203,15 @@ meta_window_actor_after_effects (MetaWindowActor *self)
meta_window_actor_sync_visibility (self);
meta_window_actor_sync_actor_geometry (self, FALSE);
+
+ if (!meta_is_wayland_compositor ())
+ {
+ if (!meta_window_is_mapped (priv->window))
+ meta_window_actor_detach_x11_pixmap (self);
+
+ if (priv->needs_pixmap)
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
+ }
}
void
@@ -1073,19 +1286,95 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
meta_window_actor_after_effects (self);
}
+/* Called to drop our reference to a window backing pixmap that we
+ * previously obtained with XCompositeNameWindowPixmap. We do this
+ * when the window is unmapped or when we want to update to a new
+ * pixmap for a new size.
+ */
+static void
+meta_window_actor_detach_x11_pixmap (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+ MetaScreen *screen = priv->screen;
+ MetaDisplay *display = meta_screen_get_display (screen);
+ Display *xdisplay = meta_display_get_xdisplay (display);
+
+ if (!priv->back_pixmap)
+ return;
+
+ /* Get rid of all references to the pixmap before freeing it; it's unclear whether
+ * you are supposed to be able to free a GLXPixmap after freeing the underlying
+ * pixmap, but it certainly doesn't work with current DRI/Mesa
+ */
+ meta_surface_actor_set_texture (priv->surface, NULL);
+ cogl_flush();
+
+ XFreePixmap (xdisplay, priv->back_pixmap);
+ priv->back_pixmap = None;
+
+ meta_window_actor_queue_create_x11_pixmap (self);
+}
+
gboolean
meta_window_actor_should_unredirect (MetaWindowActor *self)
{
+ MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
MetaWindowActorPrivate *priv = self->priv;
- return meta_surface_actor_should_unredirect (priv->surface);
+
+ if (meta_is_wayland_compositor ())
+ return FALSE;
+
+ if (meta_window_requested_dont_bypass_compositor (metaWindow))
+ return FALSE;
+
+ if (metaWindow->opacity != 0xFF)
+ return FALSE;
+
+ if (metaWindow->shape_region != NULL)
+ return FALSE;
+
+ if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
+ return FALSE;
+
+ if (!meta_window_is_monitor_sized (metaWindow))
+ return FALSE;
+
+ if (meta_window_requested_bypass_compositor (metaWindow))
+ return TRUE;
+
+ if (meta_window_is_override_redirect (metaWindow))
+ return TRUE;
+
+ if (priv->does_full_damage)
+ return TRUE;
+
+ return FALSE;
}
void
-meta_window_actor_set_unredirected (MetaWindowActor *self,
- gboolean unredirected)
+meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state)
{
- MetaWindowActorPrivate *priv = self->priv;
- meta_surface_actor_set_unredirected (priv->surface, unredirected);
+ MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
+ MetaDisplay *display = meta_window_get_display (metaWindow);
+
+ Display *xdisplay = meta_display_get_xdisplay (display);
+ Window xwin = meta_window_get_toplevel_xwindow (metaWindow);
+
+ if (state)
+ {
+ meta_error_trap_push (display);
+ XCompositeRedirectWindow (xdisplay, xwin, CompositeRedirectManual);
+ meta_error_trap_pop (display);
+ meta_window_actor_detach_x11_pixmap (self);
+ self->priv->unredirected = FALSE;
+ }
+ else
+ {
+ meta_error_trap_push (display);
+ XCompositeUnredirectWindow (xdisplay, xwin, CompositeRedirectManual);
+ meta_error_trap_pop (display);
+ self->priv->unredirected = TRUE;
+ }
}
void
@@ -1139,11 +1428,19 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
meta_window_get_input_rect (priv->window, &window_rect);
- /* When running as a Wayland compositor we catch size changes when new
- * buffers are attached */
- if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
- meta_surface_actor_x11_set_size (META_SURFACE_ACTOR_X11 (priv->surface),
- window_rect.width, window_rect.height);
+ /* When running as a display server we catch size changes when new
+ buffers are attached */
+ if (!meta_is_wayland_compositor ())
+ {
+ if (priv->last_width != window_rect.width ||
+ priv->last_height != window_rect.height)
+ {
+ priv->x11_size_changed = TRUE;
+
+ priv->last_width = window_rect.width;
+ priv->last_height = window_rect.height;
+ }
+ }
/* Normally we want freezing a window to also freeze its position; this allows
* windows to atomically move and resize together, either under app control,
@@ -1155,6 +1452,15 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
if (is_frozen (self) && !did_placement)
return;
+ if (!meta_is_wayland_compositor ())
+ {
+ if (priv->x11_size_changed)
+ {
+ meta_window_actor_queue_create_x11_pixmap (self);
+ meta_window_actor_update_shape (self);
+ }
+ }
+
if (meta_window_actor_effect_in_progress (self))
return;
@@ -1162,6 +1468,8 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
window_rect.x, window_rect.y);
clutter_actor_set_size (CLUTTER_ACTOR (self),
window_rect.width, window_rect.height);
+
+ g_signal_emit (self, signals[POSITION_CHANGED], 0);
}
void
@@ -1321,11 +1629,19 @@ meta_window_actor_new (MetaWindow *window)
NULL);
priv = self->priv;
+ priv->mapped = meta_window_toplevel_is_mapped (priv->window);
- meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
-
- if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
+ if (!meta_is_wayland_compositor ())
{
+ priv->last_width = -1;
+ priv->last_height = -1;
+
+ if (priv->mapped)
+ meta_window_actor_queue_create_x11_pixmap (self);
+
+ meta_window_actor_set_updates_frozen (self,
+ meta_window_updates_are_frozen (priv->window));
+
/* If a window doesn't start off with updates frozen, we should
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
*/
@@ -1357,6 +1673,38 @@ meta_window_actor_new (MetaWindow *window)
return self;
}
+void
+meta_window_actor_mapped (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+
+ g_return_if_fail (!priv->mapped);
+
+ priv->mapped = TRUE;
+
+ if (!meta_is_wayland_compositor ())
+ meta_window_actor_queue_create_x11_pixmap (self);
+}
+
+void
+meta_window_actor_unmapped (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+
+ g_return_if_fail (priv->mapped);
+
+ priv->mapped = FALSE;
+
+ if (meta_window_actor_effect_in_progress (self))
+ return;
+
+ if (!meta_is_wayland_compositor ())
+ {
+ meta_window_actor_detach_x11_pixmap (self);
+ priv->needs_pixmap = FALSE;
+ }
+}
+
#if 0
/* Print out a region; useful for debugging */
static void
@@ -1399,6 +1747,30 @@ see_region (cairo_region_t *region,
#endif
/**
+ * meta_window_actor_set_unobscured_region:
+ * @self: a #MetaWindowActor
+ * @unobscured_region: the region of the screen that isn't completely
+ * obscured.
+ *
+ * Provides a hint as to what areas of the window need to queue
+ * redraws when damaged. Regions not in @unobscured_region are completely obscured.
+ */
+void
+meta_window_actor_set_unobscured_region (MetaWindowActor *self,
+ cairo_region_t *unobscured_region)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+
+ if (priv->unobscured_region)
+ cairo_region_destroy (priv->unobscured_region);
+
+ if (unobscured_region)
+ priv->unobscured_region = cairo_region_copy (unobscured_region);
+ else
+ priv->unobscured_region = NULL;
+}
+
+/**
* meta_window_actor_set_clip_region_beneath:
* @self: a #MetaWindowActor
* @clip_region: the region of the screen that isn't completely
@@ -1437,6 +1809,16 @@ meta_window_actor_cull_out (MetaCullable *cullable,
{
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
+ if (!meta_is_wayland_compositor ())
+ {
+ MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
+
+ /* Don't do any culling for the unredirected window */
+ if (self == info->unredirected_window)
+ return;
+ }
+
+ meta_window_actor_set_unobscured_region (self, unobscured_region);
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
meta_window_actor_set_clip_region_beneath (self, clip_region);
}
@@ -1459,6 +1841,88 @@ cullable_iface_init (MetaCullableInterface *iface)
iface->reset_culling = meta_window_actor_reset_culling;
}
+/* When running as a wayland compositor we don't make requests for
+ * replacement pixmaps when resizing windows, we will instead be
+ * asked to attach replacement buffers by the clients. */
+static void
+check_needs_x11_pixmap (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+ MetaScreen *screen = priv->screen;
+ MetaDisplay *display = meta_screen_get_display (screen);
+ Display *xdisplay = meta_display_get_xdisplay (display);
+ MetaCompScreen *info = meta_screen_get_compositor_data (screen);
+ Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
+
+ if (!priv->needs_pixmap)
+ return;
+
+ if (!priv->mapped)
+ return;
+
+ if (xwindow == meta_screen_get_xroot (screen) ||
+ xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
+ return;
+
+ if (priv->x11_size_changed)
+ {
+ meta_window_actor_detach_x11_pixmap (self);
+ priv->x11_size_changed = FALSE;
+ }
+
+ meta_error_trap_push (display);
+
+ if (priv->back_pixmap == None)
+ {
+ CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+ CoglTexture *texture;
+
+ meta_error_trap_push (display);
+
+ priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
+
+ if (meta_error_trap_pop_with_return (display) != Success)
+ {
+ /* Probably a BadMatch if the window isn't viewable; we could
+ * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
+ * to avoid this, but there's no reason to take two round trips
+ * when one will do. (We need that Sync if we want to handle failures
+ * for any reason other than !viewable. That's unlikely, but maybe
+ * we'll BadAlloc or something.)
+ */
+ priv->back_pixmap = None;
+ }
+
+ if (priv->back_pixmap == None)
+ {
+ meta_verbose ("Unable to get named pixmap for %p\n", self);
+ goto out;
+ }
+
+ texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->back_pixmap, FALSE, NULL));
+ if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
+ g_warning ("NOTE: Not using GLX TFP!\n");
+
+ meta_surface_actor_set_texture (META_SURFACE_ACTOR (priv->surface), texture);
+
+ /* ::size-changed is supposed to refer to meta_window_get_frame_rect().
+ * Emitting it here works pretty much OK because a new value of the
+ * *input* rect (which is the outer rect with the addition of invisible
+ * borders) forces a new pixmap and we get here. In the rare case where
+ * a change to the window size was exactly balanced by a change to the
+ * invisible borders, we would miss emitting the signal. We would also
+ * emit spurious signals when we get a new pixmap without a new size,
+ * but that should be mostly harmless.
+ */
+ g_signal_emit (self, signals[SIZE_CHANGED], 0);
+ }
+
+ priv->needs_pixmap = FALSE;
+
+ out:
+ meta_error_trap_pop (display);
+}
+
static void
check_needs_shadow (MetaWindowActor *self)
{
@@ -1469,6 +1933,9 @@ check_needs_shadow (MetaWindowActor *self)
gboolean should_have_shadow;
gboolean appears_focused;
+ if (!priv->mapped)
+ return;
+
/* Calling meta_window_actor_has_shadow() here at every pre-paint is cheap
* and avoids the need to explicitly handle window type changes, which
* we would do if tried to keep track of when we might be adding or removing
@@ -1526,14 +1993,68 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
XDamageNotifyEvent *event)
{
MetaWindowActorPrivate *priv = self->priv;
+ MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
+ gboolean redraw_queued;
+ cairo_region_t *unobscured_region;
+
+ priv->received_x11_damage = TRUE;
+
+ if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self &&
!priv->unredirected)
+ {
+ MetaRectangle window_rect;
+ meta_window_get_frame_rect (priv->window, &window_rect);
+
+ if (window_rect.x == event->area.x &&
+ window_rect.y == event->area.y &&
+ window_rect.width == event->area.width &&
+ window_rect.height == event->area.height)
+ priv->full_damage_frames_count++;
+ else
+ priv->full_damage_frames_count = 0;
- g_assert (!meta_is_wayland_compositor ());
+ if (priv->full_damage_frames_count >= 100)
+ priv->does_full_damage = TRUE;
+ }
+
+ /* Drop damage event for unredirected windows */
+ if (priv->unredirected)
+ return;
+
+ if (is_frozen (self))
+ {
+ /* The window is frozen due to an effect in progress: we ignore damage
+ * here on the off chance that this will stop the corresponding
+ * texture_from_pixmap from being update.
+ *
+ * needs_damage_all tracks that some unknown damage happened while the
+ * window was frozen so that when the window becomes unfrozen we can
+ * issue a full window update to cover any lost damage.
+ *
+ * It should be noted that this is an unreliable mechanism since it's
+ * quite likely that drivers will aim to provide a zero-copy
+ * implementation of the texture_from_pixmap extension and in those cases
+ * any drawing done to the window is always immediately reflected in the
+ * texture regardless of damage event handling.
+ */
+ priv->needs_damage_all = TRUE;
+ return;
+ }
+
+ if (!priv->mapped || priv->needs_pixmap)
+ return;
+
+ unobscured_region =
+ clutter_actor_has_mapped_clones (CLUTTER_ACTOR (priv->surface))
+ ? NULL : priv->unobscured_region;
+ redraw_queued = meta_surface_actor_damage_area (priv->surface,
+ event->area.x,
+ event->area.y,
+ event->area.width,
+ event->area.height,
+ unobscured_region);
+
+ priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
- meta_surface_actor_process_damage (priv->surface,
- event->area.x,
- event->area.y,
- event->area.width,
- event->area.height);
}
void
@@ -1761,9 +2282,8 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *opaque_region;
- gboolean argb32 = is_argb32 (self);
- if (argb32 && priv->window->opaque_region != NULL)
+ if (priv->argb32 && priv->window->opaque_region != NULL)
{
MetaFrameBorders borders;
@@ -1783,7 +2303,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
cairo_region_intersect (opaque_region, priv->shape_region);
}
- else if (argb32)
+ else if (priv->argb32)
opaque_region = NULL;
else
opaque_region = cairo_region_reference (priv->shape_region);
@@ -1799,6 +2319,9 @@ check_needs_reshape (MetaWindowActor *self)
MetaFrameBorders borders;
cairo_rectangle_int_t client_area;
+ if (!priv->mapped)
+ return;
+
if (!priv->needs_reshape)
return;
@@ -1840,6 +2363,9 @@ static void
meta_window_actor_handle_updates (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
+ MetaScreen *screen = priv->screen;
+ MetaDisplay *display = meta_screen_get_display (screen);
+ Display *xdisplay = meta_display_get_xdisplay (display);
if (is_frozen (self))
{
@@ -1848,10 +2374,45 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
return;
}
- meta_surface_actor_pre_paint (priv->surface);
+ if (!meta_is_wayland_compositor ())
+ {
+ if (priv->unredirected)
+ {
+ /* Nothing to do here until/if the window gets redirected again */
+ return;
+ }
- if (!meta_surface_actor_is_visible (priv->surface))
- return;
+ if (priv->received_x11_damage)
+ {
+ meta_error_trap_push (display);
+ XDamageSubtract (xdisplay, priv->damage, None, None);
+ meta_error_trap_pop (display);
+
+ /* We need to make sure that any X drawing that happens before the
+ * XDamageSubtract() above is visible to subsequent GL rendering;
+ * the only standardized way to do this is EXT_x11_sync_object,
+ * which isn't yet widely available. For now, we count on details
+ * of Xorg and the open source drivers, and hope for the best
+ * otherwise.
+ *
+ * Xorg and open source driver specifics:
+ *
+ * The X server makes sure to flush drawing to the kernel before
+ * sending out damage events, but since we use DamageReportBoundingBox
+ * there may be drawing between the last damage event and the
+ * XDamageSubtract() that needs to be flushed as well.
+ *
+ * Xorg always makes sure that drawing is flushed to the kernel
+ * before writing events or responses to the client, so any round trip
+ * request at this point is sufficient to flush the GLX buffers.
+ */
+ XSync (xdisplay, False);
+
+ priv->received_x11_damage = FALSE;
+ }
+
+ check_needs_x11_pixmap (self);
+ }
check_needs_reshape (self);
check_needs_shadow (self);
@@ -2040,16 +2601,20 @@ void
meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen)
{
- MetaWindowActorPrivate *priv = self->priv;
+ /* On wayland we shouldn't need to ever freeze updates... */
+ if (!meta_is_wayland_compositor ())
+ {
+ MetaWindowActorPrivate *priv = self->priv;
- updates_frozen = updates_frozen != FALSE;
+ updates_frozen = updates_frozen != FALSE;
- if (priv->updates_frozen != updates_frozen)
- {
- priv->updates_frozen = updates_frozen;
- if (updates_frozen)
- meta_window_actor_freeze (self);
- else
- meta_window_actor_thaw (self);
+ if (priv->updates_frozen != updates_frozen)
+ {
+ priv->updates_frozen = updates_frozen;
+ if (updates_frozen)
+ meta_window_actor_freeze (self);
+ else
+ meta_window_actor_thaw (self);
+ }
}
}
diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c
index 5420605..9554571 100644
--- a/src/compositor/meta-window-group.c
+++ b/src/compositor/meta-window-group.c
@@ -115,6 +115,8 @@ meta_window_group_paint (ClutterActor *actor)
{
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
+ ClutterActorIter iter;
+ ClutterActor *child;
cairo_rectangle_int_t visible_rect, clip_rect;
int paint_x_offset, paint_y_offset;
int paint_x_origin, paint_y_origin;
@@ -123,6 +125,18 @@ meta_window_group_paint (ClutterActor *actor)
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
ClutterActor *stage = clutter_actor_get_stage (actor);
+ /* Start off by treating all windows as completely unobscured, so damage anywhere
+ * in a window queues redraws, but confine it more below. */
+ clutter_actor_iter_init (&iter, actor);
+ while (clutter_actor_iter_next (&iter, &child))
+ {
+ if (META_IS_WINDOW_ACTOR (child))
+ {
+ MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
+ meta_window_actor_set_unobscured_region (window_actor, NULL);
+ }
+ }
+
/* Normally we expect an actor to be drawn at it's position on the screen.
* However, if we're inside the paint of a ClutterClone, that won't be the
* case and we need to compensate. We look at the position of the window
@@ -170,8 +184,9 @@ meta_window_group_paint (ClutterActor *actor)
if (info->unredirected_window != NULL)
{
cairo_rectangle_int_t unredirected_rect;
+ MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
- meta_window_get_frame_rect (info->unredirected_window, (MetaRectangle *)&unredirected_rect);
+ meta_window_get_frame_rect (window, (MetaRectangle *)&unredirected_rect);
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
}
diff --git a/src/compositor/plugins/default.c b/src/compositor/plugins/default.c
index 892854b..91b30c0 100644
--- a/src/compositor/plugins/default.c
+++ b/src/compositor/plugins/default.c
@@ -409,7 +409,7 @@ switch_workspace (MetaPlugin *plugin,
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
gint win_workspace;
- win_workspace = meta_window_get_workspace (meta_window_actor_get_meta_window (window_actor));
+ win_workspace = meta_window_actor_get_workspace (window_actor);
if (win_workspace == to || win_workspace == from)
{
diff --git a/src/core/display.c b/src/core/display.c
index a11836c..8a98cf5 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2777,7 +2777,7 @@ handle_other_xevent (MetaDisplay *display,
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window == window &&
- window->frame == NULL)
+ ((window->frame == NULL) || !window->frame->mapped))
meta_display_end_grab_op (display, timestamp);
if (!frame_was_receiver)
diff --git a/src/core/frame.c b/src/core/frame.c
index e54e862..5fa7bee 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -62,6 +62,7 @@ meta_window_ensure_frame (MetaWindow *window)
frame->right_width = 0;
frame->current_cursor = 0;
+ frame->mapped = FALSE;
frame->is_flashing = FALSE;
frame->borders_cached = FALSE;
@@ -156,8 +157,6 @@ meta_window_ensure_frame (MetaWindow *window)
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);
-
- meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
}
void
diff --git a/src/core/frame.h b/src/core/frame.h
index 8ac1c26..0f1ebea 100644
--- a/src/core/frame.h
+++ b/src/core/frame.h
@@ -47,6 +47,7 @@ struct _MetaFrame
int right_width;
int bottom_height;
+ guint mapped : 1;
guint need_reapply_frame_shape : 1;
guint is_flashing : 1; /* used by the visual bell flash */
guint borders_cached : 1;
diff --git a/src/core/window.c b/src/core/window.c
index 13d8e2a..b4a845d 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -215,8 +215,6 @@ enum
FOCUS,
RAISED,
UNMANAGED,
- SIZE_CHANGED,
- POSITION_CHANGED,
LAST_SIGNAL
};
@@ -613,22 +611,6 @@ meta_window_class_init (MetaWindowClass *klass)
G_STRUCT_OFFSET (MetaWindowClass, unmanaged),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
-
- window_signals[POSITION_CHANGED] =
- g_signal_new ("position-changed",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- window_signals[SIZE_CHANGED] =
- g_signal_new ("size-changed",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
}
static void
@@ -810,35 +792,6 @@ meta_window_should_attach_to_parent (MetaWindow *window)
}
}
-static gboolean
-client_window_should_be_mapped (MetaWindow *window)
-{
- return !window->shaded;
-}
-
-static void
-sync_client_window_mapped (MetaWindow *window)
-{
- gboolean should_be_mapped = client_window_should_be_mapped (window);
-
- if (window->mapped == should_be_mapped)
- return;
-
- window->mapped = should_be_mapped;
-
- meta_error_trap_push (window->display);
- if (should_be_mapped)
- {
- XMapWindow (window->display->xdisplay, window->xwindow);
- }
- else
- {
- XUnmapWindow (window->display->xdisplay, window->xwindow);
- window->unmaps_pending ++;
- }
- meta_error_trap_pop (window->display);
-}
-
static MetaWindow*
meta_window_new_shared (MetaDisplay *display,
MetaScreen *screen,
@@ -1334,6 +1287,9 @@ meta_window_new_shared (MetaDisplay *display,
set_net_wm_state (window);
}
+ if (screen->display->compositor)
+ meta_compositor_add_window (screen->display->compositor, window);
+
/* Sync stack changes */
meta_stack_thaw (window->screen->stack);
@@ -1347,8 +1303,6 @@ meta_window_new_shared (MetaDisplay *display,
/* disable show desktop mode unless we're a desktop component */
maybe_leave_show_desktop_mode (window);
- sync_client_window_mapped (window);
-
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
/* See bug 303284; a transient of the given window can already exist, in which
* case we think it should probably be shown.
@@ -1613,8 +1567,7 @@ meta_window_new (MetaDisplay *display,
META_WINDOW_CLIENT_TYPE_X11,
NULL,
xwindow,
- /* XXX */
- !meta_is_wayland_compositor (),
+ TRUE,
existing_wm_state,
effect,
&attrs);
@@ -1807,13 +1760,10 @@ meta_window_unmanage (MetaWindow *window,
if (window->display->compositor)
{
if (window->visible_to_compositor)
- {
- meta_compositor_hide_window (window->display->compositor, window,
- META_COMP_EFFECT_DESTROY);
+ meta_compositor_hide_window (window->display->compositor, window,
+ META_COMP_EFFECT_DESTROY);
- /* XXX - support destroy effects better */
- meta_compositor_remove_window (window->display->compositor, window);
- }
+ meta_compositor_remove_window (window->display->compositor, window);
}
if (window->display->window_with_menu == window)
@@ -2396,8 +2346,6 @@ implement_showing (MetaWindow *window,
meta_verbose ("Implement showing = %d for window %s\n",
showing, window->desc);
- sync_client_window_mapped (window);
-
if (!showing)
{
/* When we manage a new window, we normally delay placing it
@@ -2986,6 +2934,94 @@ window_would_be_covered (const MetaWindow *newbie)
return FALSE; /* none found */
}
+static gboolean
+map_frame (MetaWindow *window)
+{
+ if (window->frame && !window->frame->mapped)
+ {
+ meta_topic (META_DEBUG_WINDOW_STATE,
+ "Frame actually needs map\n");
+ window->frame->mapped = TRUE;
+ meta_ui_map_frame (window->screen->ui, window->frame->xwindow);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static gboolean
+map_client_window (MetaWindow *window)
+{
+ if (!window->mapped)
+ {
+ meta_topic (META_DEBUG_WINDOW_STATE,
+ "%s actually needs map\n", window->desc);
+ window->mapped = TRUE;
+ meta_error_trap_push (window->display);
+ XMapWindow (window->display->xdisplay, window->xwindow);
+ meta_error_trap_pop (window->display);
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static gboolean
+unmap_client_window (MetaWindow *window,
+ const char *reason)
+{
+ if (window->mapped)
+ {
+ meta_topic (META_DEBUG_WINDOW_STATE,
+ "%s actually needs unmap%s\n",
+ window->desc, reason);
+ meta_topic (META_DEBUG_WINDOW_STATE,
+ "Incrementing unmaps_pending on %s%s\n",
+ window->desc, reason);
+ window->mapped = FALSE;
+ window->unmaps_pending += 1;
+ meta_error_trap_push (window->display);
+ XUnmapWindow (window->display->xdisplay, window->xwindow);
+ meta_error_trap_pop (window->display);
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * meta_window_is_mapped:
+ * @window: a #MetaWindow
+ *
+ * Determines whether the X window for the MetaWindow is mapped.
+ */
+gboolean
+meta_window_is_mapped (MetaWindow *window)
+{
+ return window->mapped;
+}
+
+/**
+ * meta_window_toplevel_is_mapped:
+ * @window: a #MetaWindow
+ *
+ * Determines whether the toplevel X window for the MetaWindow is
+ * mapped. (The frame window is mapped even without the client window
+ * when a window is shaded.)
+ *
+ * Return Value: %TRUE if the toplevel is mapped.
+ */
+gboolean
+meta_window_toplevel_is_mapped (MetaWindow *window)
+{
+ /* The frame is mapped but not the client window when the window
+ * is shaded.
+ */
+ return window->mapped || (window->frame && window->frame->mapped);
+}
+
static void
meta_window_force_placement (MetaWindow *window)
{
@@ -3024,12 +3060,16 @@ meta_window_show (MetaWindow *window)
gboolean place_on_top_on_map;
gboolean needs_stacking_adjustment;
MetaWindow *focus_window;
+ gboolean toplevel_was_mapped;
+ gboolean toplevel_now_mapped;
gboolean notify_demands_attention = FALSE;
meta_topic (META_DEBUG_WINDOW_STATE,
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
window->desc, window->shaded, window->iconic, window->placed);
+ toplevel_was_mapped = meta_window_toplevel_is_mapped (window);
+
focus_window = window->display->focus_window; /* May be NULL! */
did_show = FALSE;
window_state_on_map (window, &takes_focus_on_map, &place_on_top_on_map);
@@ -3156,18 +3196,46 @@ meta_window_show (MetaWindow *window)
}
}
- if (window->hidden)
+ /* Shaded means the frame is mapped but the window is not */
+
+ if (map_frame (window))
+ did_show = TRUE;
+
+ if (window->shaded)
{
- meta_stack_freeze (window->screen->stack);
- window->hidden = FALSE;
- meta_stack_thaw (window->screen->stack);
- did_show = TRUE;
+ unmap_client_window (window, " (shading)");
+
+ if (!window->iconic)
+ {
+ window->iconic = TRUE;
+ set_wm_state (window, IconicState);
+ }
}
+ else
+ {
+ if (map_client_window (window))
+ did_show = TRUE;
- if (window->iconic)
+ if (window->hidden)
+ {
+ meta_stack_freeze (window->screen->stack);
+ window->hidden = FALSE;
+ meta_stack_thaw (window->screen->stack);
+ did_show = TRUE;
+ }
+
+ if (window->iconic)
+ {
+ window->iconic = FALSE;
+ set_wm_state (window, NormalState);
+ }
+ }
+
+ toplevel_now_mapped = meta_window_toplevel_is_mapped (window);
+ if (toplevel_now_mapped != toplevel_was_mapped)
{
- window->iconic = FALSE;
- set_wm_state (window, NormalState);
+ if (window->display->compositor)
+ meta_compositor_window_mapped (window->display->compositor, window);
}
if (!window->visible_to_compositor)
@@ -3190,8 +3258,8 @@ meta_window_show (MetaWindow *window)
break;
}
- meta_compositor_add_window (window->display->compositor, window);
- meta_compositor_show_window (window->display->compositor, window, effect);
+ meta_compositor_show_window (window->display->compositor,
+ window, effect);
}
}
@@ -3259,10 +3327,14 @@ static void
meta_window_hide (MetaWindow *window)
{
gboolean did_hide;
+ gboolean toplevel_was_mapped;
+ gboolean toplevel_now_mapped;
meta_topic (META_DEBUG_WINDOW_STATE,
"Hiding window %s\n", window->desc);
+ toplevel_was_mapped = meta_window_toplevel_is_mapped (window);
+
if (window->visible_to_compositor)
{
window->visible_to_compositor = FALSE;
@@ -3283,12 +3355,19 @@ meta_window_hide (MetaWindow *window)
break;
}
- meta_compositor_hide_window (window->display->compositor, window, effect);
+ meta_compositor_hide_window (window->display->compositor,
+ window, effect);
}
}
did_hide = FALSE;
+ /* If this is the first time that we've calculating the showing
+ * state of the window, the frame and client window might not
+ * yet be mapped, so we need to map them now */
+ map_frame (window);
+ map_client_window (window);
+
if (!window->hidden)
{
meta_stack_freeze (window->screen->stack);
@@ -3304,6 +3383,19 @@ meta_window_hide (MetaWindow *window)
set_wm_state (window, IconicState);
}
+ toplevel_now_mapped = meta_window_toplevel_is_mapped (window);
+ if (toplevel_now_mapped != toplevel_was_mapped)
+ {
+ if (window->display->compositor)
+ {
+ /* As above, we may be *mapping* live hidden windows */
+ if (toplevel_now_mapped)
+ meta_compositor_window_mapped (window->display->compositor, window);
+ else
+ meta_compositor_window_unmapped (window->display->compositor, window);
+ }
+ }
+
set_net_wm_state (window);
if (did_hide && window->struts)
@@ -5396,12 +5488,6 @@ meta_window_move_resize_internal (MetaWindow *window,
else if (is_user_action)
save_user_window_placement (window);
- if (need_move_frame)
- g_signal_emit (window, window_signals[POSITION_CHANGED], 0);
-
- if (need_resize_client)
- g_signal_emit (window, window_signals[SIZE_CHANGED], 0);
-
if (need_move_frame || need_resize_frame ||
need_move_client || need_resize_client ||
did_placement || is_wayland_resize)
@@ -8131,7 +8217,7 @@ redraw_icon (MetaWindow *window)
/* We could probably be smart and just redraw the icon here,
* instead of the whole frame.
*/
- if (window->frame)
+ if (window->frame && (window->mapped || window->frame->mapped))
meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow);
}
diff --git a/src/meta/compositor.h b/src/meta/compositor.h
index 45c8b09..42ff0dd 100644
--- a/src/meta/compositor.h
+++ b/src/meta/compositor.h
@@ -75,10 +75,11 @@ gboolean meta_compositor_filter_keybinding (MetaCompositor *compositor,
MetaScreen *screen,
MetaKeyBinding *binding);
-void meta_compositor_add_window (MetaCompositor *compositor,
- MetaWindow *window);
-void meta_compositor_remove_window (MetaCompositor *compositor,
- MetaWindow *window);
+void meta_compositor_add_window (MetaCompositor *compositor,
+ MetaWindow *window);
+void meta_compositor_remove_window (MetaCompositor *compositor,
+ MetaWindow *window);
+
void meta_compositor_show_window (MetaCompositor *compositor,
MetaWindow *window,
MetaCompEffect effect);
@@ -100,6 +101,10 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
+void meta_compositor_window_mapped (MetaCompositor *compositor,
+ MetaWindow *window);
+void meta_compositor_window_unmapped (MetaCompositor *compositor,
+ MetaWindow *window);
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
gboolean did_placement);
diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h
index 2055ca8..9f808a9 100644
--- a/src/meta/meta-window-actor.h
+++ b/src/meta/meta-window-actor.h
@@ -58,8 +58,11 @@ struct _MetaWindowActor
GType meta_window_actor_get_type (void);
Window meta_window_actor_get_x_window (MetaWindowActor *self);
+gint meta_window_actor_get_workspace (MetaWindowActor *self);
MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self);
ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self);
+gboolean meta_window_actor_is_override_redirect (MetaWindowActor *self);
+gboolean meta_window_actor_showing_on_its_workspace (MetaWindowActor *self);
gboolean meta_window_actor_is_destroyed (MetaWindowActor *self);
#endif /* META_WINDOW_ACTOR_H */
diff --git a/src/meta/window.h b/src/meta/window.h
index 430dc6b..ff2d037 100644
--- a/src/meta/window.h
+++ b/src/meta/window.h
@@ -189,6 +189,8 @@ gboolean meta_window_requested_bypass_compositor (MetaWindow *window);
gboolean meta_window_requested_dont_bypass_compositor (MetaWindow *window);
gint *meta_window_get_all_monitors (MetaWindow *window, gsize *length);
+gboolean meta_window_is_mapped (MetaWindow *window);
+gboolean meta_window_toplevel_is_mapped (MetaWindow *window);
gboolean meta_window_get_icon_geometry (MetaWindow *window,
MetaRectangle *rect);
void meta_window_set_icon_geometry (MetaWindow *window,
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 43ed925..1ca38e5 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -44,11 +44,11 @@
#include "meta-wayland-private.h"
#include "meta-xwayland-private.h"
#include "meta-wayland-stage.h"
+#include "meta-surface-actor.h"
#include "meta-wayland-seat.h"
#include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-data-device.h"
-
#include "meta-cursor-tracker-private.h"
#include "display-private.h"
#include "window-private.h"
@@ -58,9 +58,6 @@
#include "meta-idle-monitor-private.h"
#include "monitor-private.h"
-#include "meta-surface-actor.h"
-#include "meta-surface-actor-wayland.h"
-
static void
surface_process_damage (MetaWaylandSurface *surface,
cairo_region_t *region)
@@ -71,8 +68,12 @@ surface_process_damage (MetaWaylandSurface *surface,
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
- meta_surface_actor_process_damage (surface->surface_actor,
- rect.x, rect.y, rect.width, rect.height);
+ meta_surface_actor_damage_area (surface->surface_actor,
+ rect.x,
+ rect.y,
+ rect.width,
+ rect.height,
+ NULL);
}
}
@@ -263,7 +264,7 @@ actor_surface_commit (MetaWaylandSurface *surface)
{
ensure_buffer_texture (buffer);
meta_wayland_buffer_reference (&surface->buffer_ref, buffer);
- meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
+ meta_surface_actor_attach_wayland_buffer (surface_actor, buffer);
changed = TRUE;
}
@@ -504,7 +505,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface_handle_pending_buffer_destroy;
wl_list_init (&surface->pending.frame_callback_list);
- surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
+ surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ());
return surface;
}
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index c9be272..02c5b7b 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -48,8 +48,6 @@ xserver_set_window_id (struct wl_client *client,
{
surface->window = window;
window->surface = surface;
-
- meta_window_set_surface_mapped (window, TRUE);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]