1
0
Fork 0

Revert unintentional merge from wip/surface-content to wayland

This reverts a lot of commits.
This commit is contained in:
Jasper St. Pierre 2014-01-22 09:16:56 -05:00
parent 59f79e8294
commit 20545941fa
23 changed files with 1141 additions and 1313 deletions

View file

@ -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

View file

@ -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 \

View file

@ -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;

View file

@ -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));
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
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);
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);
}
@ -1360,6 +1402,30 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
sync_actor_stacking (info);
}
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,
@ -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);

View file

@ -1,159 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-surface-actor-wayland.h"
#include <cogl/cogl-wayland-server.h>
#include "meta-shaped-texture-private.h"
struct _MetaSurfaceActorWaylandPrivate
{
MetaWaylandSurface *surface;
MetaWaylandBuffer *buffer;
};
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
static void
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
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);
}
meta_surface_actor_redraw_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
{
}
static gboolean
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
{
/* TODO: look at the SHM buffer pixel format */
return TRUE;
}
static gboolean
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
{
/* TODO: ensure that the buffer isn't NULL, implement
* wayland mapping semantics */
return TRUE;
}
static void
meta_surface_actor_wayland_freeze (MetaSurfaceActor *actor)
{
}
static void
meta_surface_actor_wayland_thaw (MetaSurfaceActor *actor)
{
}
static gboolean
meta_surface_actor_wayland_is_frozen (MetaSurfaceActor *actor)
{
return FALSE;
}
static gboolean
meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
{
return FALSE;
}
static void
meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
/* Do nothing. In the future, we'll use KMS to set this
* up as a hardware overlay or something. */
}
static void
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
{
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
surface_actor_class->freeze = meta_surface_actor_wayland_freeze;
surface_actor_class->thaw = meta_surface_actor_wayland_thaw;
surface_actor_class->is_frozen = meta_surface_actor_wayland_is_frozen;
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
}
static void
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
{
}
MetaSurfaceActor *
meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
{
MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
g_assert (meta_is_wayland_compositor ());
priv->surface = surface;
return META_SURFACE_ACTOR (self);
}
void
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
priv->buffer = buffer;
if (buffer)
meta_shaped_texture_set_texture (stex, buffer->texture);
else
meta_shaped_texture_set_texture (stex, NULL);
}

View file

@ -1,65 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
#define __META_SURFACE_ACTOR_WAYLAND_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include "meta-wayland-private.h"
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland;
typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
struct _MetaSurfaceActorWayland
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorWaylandClass
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_wayland_get_type (void);
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */

View file

@ -1,551 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-surface-actor-x11.h"
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <meta/errors.h>
#include "window-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-cullable.h"
struct _MetaSurfaceActorX11Private
{
MetaWindow *window;
MetaDisplay *display;
CoglTexture *texture;
Pixmap pixmap;
Damage damage;
int last_width;
int last_height;
/* Freeze/thaw accounting */
guint freeze_count;
/* This is used to detect fullscreen windows that need to be unredirected */
guint full_damage_frames_count;
guint does_full_damage : 1;
/* Other state... */
guint argb32 : 1;
guint received_damage : 1;
guint size_changed : 1;
guint needs_damage_all : 1;
guint unredirected : 1;
};
typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)
G_ADD_PRIVATE (MetaSurfaceActorX11))
static MetaCullableInterface *parent_cullable_iface;
static void
meta_surface_actor_x11_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (cullable);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
/* Don't do any culling for the unredirected window */
if (priv->unredirected)
return;
parent_cullable_iface->cull_out (cullable, unobscured_region, clip_region);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
parent_cullable_iface = g_type_interface_peek_parent (iface);
iface->cull_out = meta_surface_actor_x11_cull_out;
}
static void
free_damage (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (priv->damage == None)
return;
meta_error_trap_push (display);
XDamageDestroy (xdisplay, priv->damage);
priv->damage = None;
meta_error_trap_pop (display);
}
static void
detach_pixmap (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
if (priv->pixmap == None)
return;
meta_error_trap_push (display);
XFreePixmap (xdisplay, priv->pixmap);
priv->pixmap = None;
meta_error_trap_pop (display);
meta_shaped_texture_set_texture (stex, NULL);
cogl_object_unref (priv->texture);
priv->texture = NULL;
}
static void
set_pixmap (MetaSurfaceActorX11 *self,
Pixmap pixmap)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
CoglTexture *texture;
g_assert (priv->pixmap == None);
priv->pixmap = pixmap;
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->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");
priv->texture = texture;
meta_shaped_texture_set_texture (stex, texture);
}
static void
update_pixmap (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (priv->size_changed)
{
detach_pixmap (self);
priv->size_changed = FALSE;
}
if (priv->pixmap == None)
{
Pixmap new_pixmap;
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
new_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.)
*/
new_pixmap = None;
}
if (new_pixmap == None)
{
meta_verbose ("Unable to get named pixmap for %s\n",
meta_window_get_description (priv->window));
return;
}
set_pixmap (self, new_pixmap);
}
}
static gboolean
is_frozen (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return (priv->freeze_count > 0);
}
static gboolean
is_visible (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return (priv->pixmap != None) && !priv->unredirected;
}
static void
damage_area (MetaSurfaceActorX11 *self,
int x, int y, int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (!is_visible (self))
return;
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
meta_surface_actor_redraw_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
damage_all (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (!is_visible (self))
return;
damage_area (self, 0, 0, cogl_texture_get_width (priv->texture), cogl_texture_get_height (priv->texture));
}
static void
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->received_damage = TRUE;
if (!priv->unredirected && !priv->does_full_damage)
{
MetaRectangle window_rect;
meta_window_get_frame_rect (priv->window, &window_rect);
if (window_rect.x == x &&
window_rect.y == y &&
window_rect.width == width &&
window_rect.height == height)
priv->full_damage_frames_count++;
else
priv->full_damage_frames_count = 0;
if (priv->full_damage_frames_count >= 100)
priv->does_full_damage = TRUE;
}
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;
}
damage_area (self, x, y, width, height);
}
static void
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (is_frozen (self))
return;
if (priv->received_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_damage = FALSE;
}
update_pixmap (self);
}
static void
meta_surface_actor_x11_freeze (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->freeze_count ++;
}
static void
meta_surface_actor_x11_thaw (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->freeze_count == 0)
{
g_critical ("Error in freeze/thaw accounting.");
return;
}
priv->freeze_count --;
/* 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 (priv->needs_damage_all)
{
damage_all (self);
priv->needs_damage_all = FALSE;
}
}
static gboolean
meta_surface_actor_x11_is_frozen (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
return is_frozen (self);
}
static void
update_is_argb32 (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
XRenderPictFormat *format;
format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
}
static gboolean
meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return priv->argb32;
}
static gboolean
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
return is_visible (self);
}
static gboolean
meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaWindow *window = priv->window;
if (meta_window_requested_dont_bypass_compositor (window))
return FALSE;
if (window->opacity != 0xFF)
return FALSE;
if (window->shape_region != NULL)
return FALSE;
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
return FALSE;
if (!meta_window_is_monitor_sized (window))
return FALSE;
if (meta_window_requested_bypass_compositor (window))
return TRUE;
if (meta_window_is_override_redirect (window))
return TRUE;
if (priv->does_full_damage)
return TRUE;
return FALSE;
}
static void
sync_unredirected (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
if (priv->unredirected)
{
detach_pixmap (self);
XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
}
else
{
XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
}
meta_error_trap_pop (display);
}
static void
meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->unredirected == unredirected)
return;
priv->unredirected = unredirected;
sync_unredirected (self);
}
static void
meta_surface_actor_x11_dispose (GObject *object)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
detach_pixmap (self);
free_damage (self);
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
}
static void
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
object_class->dispose = meta_surface_actor_x11_dispose;
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
surface_actor_class->freeze = meta_surface_actor_x11_freeze;
surface_actor_class->thaw = meta_surface_actor_x11_thaw;
surface_actor_class->is_frozen = meta_surface_actor_x11_is_frozen;
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
}
static void
meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->last_width = -1;
priv->last_height = -1;
}
MetaSurfaceActor *
meta_surface_actor_x11_new (MetaWindow *window)
{
MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = meta_window_get_display (window);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwindow = meta_window_get_toplevel_xwindow (window);
g_assert (!meta_is_wayland_compositor ());
priv->window = window;
priv->display = display;
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
update_is_argb32 (self);
priv->unredirected = FALSE;
sync_unredirected (self);
return META_SURFACE_ACTOR (self);
}
void
meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->last_width == width &&
priv->last_height == height)
return;
priv->size_changed = TRUE;
priv->last_width = width;
priv->last_height = height;
}

View file

@ -1,69 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_X11_H__
#define __META_SURFACE_ACTOR_X11_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include <X11/extensions/Xdamage.h>
#include <meta/display.h>
#include <meta/window.h>
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ())
#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11))
#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11))
#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11;
typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
struct _MetaSurfaceActorX11
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorX11Class
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_x11_get_type (void);
MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_X11_H__ */

View file

@ -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,34 +84,80 @@ 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,
0, 0,
cogl_texture_get_width (texture),
cogl_texture_get_height (texture),
unobscured_region);
}
gboolean
meta_surface_actor_damage_area (MetaSurfaceActor *self,
int x,
int y,
int width,
int height,
cairo_region_t *unobscured_region)
{
MetaSurfaceActorPrivate *priv = self->priv;
update_area (self, x, y, width, height);
return meta_shaped_texture_update_area (priv->texture,
x, y, width, height,
effective_unobscured_region (self));
unobscured_region);
}
gboolean
meta_surface_actor_is_obscured (MetaSurfaceActor *self)
void
meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
MetaWaylandBuffer *buffer)
{
MetaSurfaceActorPrivate *priv = self->priv;
priv->buffer = buffer;
if (priv->unobscured_region)
return cairo_region_is_empty (priv->unobscured_region);
if (buffer)
meta_shaped_texture_set_texture (priv->texture, buffer->texture);
else
return FALSE;
meta_shaped_texture_set_texture (priv->texture, NULL);
}
void
meta_surface_actor_set_texture (MetaSurfaceActor *self,
CoglTexture *texture)
{
MetaSurfaceActorPrivate *priv = self->priv;
meta_shaped_texture_set_texture (priv->texture, texture);
}
void
@ -204,58 +176,8 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
meta_shaped_texture_set_opaque_region (priv->texture, region);
}
void
meta_surface_actor_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
MetaSurfaceActor *
meta_surface_actor_new (void)
{
META_SURFACE_ACTOR_GET_CLASS (actor)->process_damage (actor, x, y, width, height);
}
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)
{
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);
}
void
meta_surface_actor_freeze (MetaSurfaceActor *actor)
{
META_SURFACE_ACTOR_GET_CLASS (actor)->freeze (actor);
}
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)
{
return META_SURFACE_ACTOR_GET_CLASS (actor)->should_unredirect (actor);
}
void
meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
META_SURFACE_ACTOR_GET_CLASS (actor)->set_unredirected (actor, unredirected);
return g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
}

View file

@ -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 */

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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->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);
}
}
if (window->iconic)
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);
}

View file

@ -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);

View file

@ -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 */

View file

@ -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,

View file

@ -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;
}

View file

@ -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);
}
}