mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -05:00
2008-09-16 Tomas Frydrych <tf@linux.intel.com>
* clutter/glx/clutter-glx-texture-pixmap.c: * clutter/x11/clutter-x11-texture-pixmap.c: TFP resyncing on MapNotify/ConfigureNotify (bug 1020; patch by Andy Wingo <wingo@pobox.com>).
This commit is contained in:
parent
7294239d64
commit
8be7e29a6b
@ -1,3 +1,10 @@
|
||||
2008-09-16 Tomas Frydrych <tf@linux.intel.com>
|
||||
|
||||
* clutter/glx/clutter-glx-texture-pixmap.c:
|
||||
* clutter/x11/clutter-x11-texture-pixmap.c:
|
||||
TFP resyncing on MapNotify/ConfigureNotify (bug 1020; patch by
|
||||
Andy Wingo <wingo@pobox.com>).
|
||||
|
||||
2008-09-15 Øyvind Kolås <pippin@linux.intel.com>
|
||||
|
||||
* clutter/clutter-main.c: amended typo in gtk-doc.
|
||||
|
@ -536,12 +536,7 @@ clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
|
||||
{
|
||||
priv->glx_pixmap = glx_pixmap;
|
||||
|
||||
if (!clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture)))
|
||||
{
|
||||
create_cogl_texture (CLUTTER_TEXTURE (texture),
|
||||
pixmap_width,
|
||||
pixmap_height);
|
||||
}
|
||||
create_cogl_texture (CLUTTER_TEXTURE (texture), pixmap_width, pixmap_height);
|
||||
|
||||
CLUTTER_NOTE (TEXTURE, "Created GLXPixmap");
|
||||
|
||||
|
@ -63,7 +63,12 @@ enum
|
||||
PROP_DEPTH,
|
||||
PROP_AUTO,
|
||||
PROP_WINDOW,
|
||||
PROP_WINDOW_REDIRECT_AUTOMATIC
|
||||
PROP_WINDOW_REDIRECT_AUTOMATIC,
|
||||
PROP_WINDOW_MAPPED,
|
||||
PROP_DESTROYED,
|
||||
PROP_WINDOW_X,
|
||||
PROP_WINDOW_Y,
|
||||
PROP_WINDOW_OVERRIDE_REDIRECT
|
||||
};
|
||||
|
||||
enum
|
||||
@ -82,6 +87,10 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
static void
|
||||
clutter_x11_texture_pixmap_set_mapped (ClutterX11TexturePixmap *texture, gboolean mapped);
|
||||
static void
|
||||
clutter_x11_texture_pixmap_destroyed (ClutterX11TexturePixmap *texture);
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
@ -99,8 +108,14 @@ struct _ClutterX11TexturePixmapPrivate
|
||||
Damage damage;
|
||||
Drawable damage_drawable;
|
||||
|
||||
/* FIXME: lots of gbooleans. coalesce into bitfields */
|
||||
gboolean have_shm;
|
||||
gboolean window_redirect_automatic;
|
||||
gboolean window_mapped;
|
||||
gboolean destroyed;
|
||||
gboolean owns_pixmap;
|
||||
gboolean override_redirect;
|
||||
gint window_x, window_y;
|
||||
};
|
||||
|
||||
static int _damage_event_base = 0;
|
||||
@ -295,6 +310,40 @@ on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data)
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
}
|
||||
|
||||
static ClutterX11FilterReturn
|
||||
on_x_event_filter_too (XEvent *xev, ClutterEvent *cev, gpointer data)
|
||||
{
|
||||
ClutterX11TexturePixmap *texture;
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
|
||||
texture = CLUTTER_X11_TEXTURE_PIXMAP (data);
|
||||
|
||||
g_return_val_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture), \
|
||||
CLUTTER_X11_FILTER_CONTINUE);
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
if (xev->xany.window != priv->window)
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
|
||||
switch (xev->type) {
|
||||
case MapNotify:
|
||||
case ConfigureNotify:
|
||||
clutter_x11_texture_pixmap_sync_window (texture);
|
||||
break;
|
||||
case UnmapNotify:
|
||||
clutter_x11_texture_pixmap_set_mapped (texture, FALSE);
|
||||
break;
|
||||
case DestroyNotify:
|
||||
clutter_x11_texture_pixmap_destroyed (texture);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_damage_resources (ClutterX11TexturePixmap *texture)
|
||||
@ -344,6 +393,11 @@ clutter_x11_texture_pixmap_init (ClutterX11TexturePixmap *self)
|
||||
self->priv->pixmap_width = 0;
|
||||
self->priv->shminfo.shmid = -1;
|
||||
self->priv->window_redirect_automatic = TRUE;
|
||||
self->priv->window_mapped = FALSE;
|
||||
self->priv->destroyed = FALSE;
|
||||
self->priv->override_redirect = FALSE;
|
||||
self->priv->window_x = 0;
|
||||
self->priv->window_y = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -354,6 +408,14 @@ clutter_x11_texture_pixmap_dispose (GObject *object)
|
||||
|
||||
free_damage_resources (texture);
|
||||
|
||||
clutter_x11_remove_filter (on_x_event_filter_too, (gpointer)texture);
|
||||
|
||||
if (priv->owns_pixmap && priv->pixmap)
|
||||
{
|
||||
XFreePixmap (clutter_x11_get_default_display (), priv->pixmap);
|
||||
priv->pixmap = None;
|
||||
}
|
||||
|
||||
if (priv->image)
|
||||
{
|
||||
XDestroyImage (priv->image);
|
||||
@ -439,6 +501,21 @@ clutter_x11_texture_pixmap_get_property (GObject *object,
|
||||
case PROP_WINDOW_REDIRECT_AUTOMATIC:
|
||||
g_value_set_boolean (value, priv->window_redirect_automatic);
|
||||
break;
|
||||
case PROP_WINDOW_MAPPED:
|
||||
g_value_set_boolean (value, priv->window_mapped);
|
||||
break;
|
||||
case PROP_DESTROYED:
|
||||
g_value_set_boolean (value, priv->destroyed);
|
||||
break;
|
||||
case PROP_WINDOW_X:
|
||||
g_value_set_int (value, priv->window_x);
|
||||
break;
|
||||
case PROP_WINDOW_Y:
|
||||
g_value_set_int (value, priv->window_y);
|
||||
break;
|
||||
case PROP_WINDOW_OVERRIDE_REDIRECT:
|
||||
g_value_set_boolean (value, priv->override_redirect);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -548,6 +625,52 @@ clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
|
||||
PROP_WINDOW_REDIRECT_AUTOMATIC, pspec);
|
||||
|
||||
|
||||
pspec = g_param_spec_boolean ("window-mapped",
|
||||
"Window Mapped",
|
||||
"If window is mapped",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WINDOW_MAPPED, pspec);
|
||||
|
||||
|
||||
pspec = g_param_spec_boolean ("destroyed",
|
||||
"Destroyed",
|
||||
"If window has been destroyed",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DESTROYED, pspec);
|
||||
|
||||
pspec = g_param_spec_int ("window-x",
|
||||
"Window X",
|
||||
"X position of window on screen according to X11",
|
||||
G_MININT, G_MAXINT, 0, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WINDOW_X, pspec);
|
||||
|
||||
|
||||
pspec = g_param_spec_int ("window-y",
|
||||
"Window Y",
|
||||
"Y position of window on screen according to X11",
|
||||
G_MININT, G_MAXINT, 0, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WINDOW_Y, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("window-override-redirect",
|
||||
"Window Override Redirect",
|
||||
"If this is an override-redirect window",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WINDOW_OVERRIDE_REDIRECT, pspec);
|
||||
|
||||
|
||||
/**
|
||||
* ClutterX11TexturePixmap::update-area:
|
||||
* @texture: the object which received the signal
|
||||
@ -895,6 +1018,9 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
||||
|
||||
if (priv->pixmap != pixmap)
|
||||
{
|
||||
if (priv->pixmap && priv->owns_pixmap)
|
||||
XFreePixmap (clutter_x11_get_default_display (), priv->pixmap);
|
||||
|
||||
priv->pixmap = pixmap;
|
||||
new_pixmap = TRUE;
|
||||
}
|
||||
@ -929,7 +1055,6 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
||||
g_object_notify (G_OBJECT (texture), "pixmap-height");
|
||||
if (new_pixmap_depth)
|
||||
g_object_notify (G_OBJECT (texture), "pixmap-depth");
|
||||
g_object_unref (texture);
|
||||
|
||||
free_shm_resources (texture);
|
||||
|
||||
@ -945,6 +1070,13 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
||||
priv->pixmap_height);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep ref until here in case a notify causes removal from the scene; can't
|
||||
* lower the notifies because glx's notify handler needs to run before
|
||||
* update_area
|
||||
*/
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -967,6 +1099,8 @@ clutter_x11_texture_pixmap_set_window (ClutterX11TexturePixmap *texture,
|
||||
gboolean automatic)
|
||||
{
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
XWindowAttributes attr;
|
||||
Display *dpy = clutter_x11_get_default_display ();
|
||||
|
||||
g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture));
|
||||
|
||||
@ -980,6 +1114,7 @@ clutter_x11_texture_pixmap_set_window (ClutterX11TexturePixmap *texture,
|
||||
|
||||
if (priv->window)
|
||||
{
|
||||
clutter_x11_remove_filter (on_x_event_filter_too, (gpointer)texture);
|
||||
clutter_x11_trap_x_errors ();
|
||||
XCompositeUnredirectWindow(clutter_x11_get_default_display (),
|
||||
priv->window,
|
||||
@ -989,28 +1124,50 @@ clutter_x11_texture_pixmap_set_window (ClutterX11TexturePixmap *texture,
|
||||
clutter_x11_untrap_x_errors ();
|
||||
}
|
||||
|
||||
|
||||
priv->window = window;
|
||||
priv->window_redirect_automatic = automatic;
|
||||
priv->window_mapped = FALSE;
|
||||
priv->destroyed = FALSE;
|
||||
|
||||
if (window == None)
|
||||
return;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
{
|
||||
if (!XGetWindowAttributes (dpy, window, &attr))
|
||||
{
|
||||
XSync (dpy, False);
|
||||
clutter_x11_untrap_x_errors ();
|
||||
g_warning ("bad window 0x%x", (guint32)window);
|
||||
priv->window = None;
|
||||
return;
|
||||
}
|
||||
|
||||
XCompositeRedirectWindow
|
||||
(clutter_x11_get_default_display (),
|
||||
(dpy,
|
||||
window,
|
||||
automatic ?
|
||||
CompositeRedirectAutomatic : CompositeRedirectManual);
|
||||
XSync (clutter_x11_get_default_display (), False);
|
||||
XSync (dpy, False);
|
||||
}
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
|
||||
if (priv->window)
|
||||
{
|
||||
XSelectInput (dpy, priv->window,
|
||||
attr.your_event_mask | StructureNotifyMask);
|
||||
clutter_x11_add_filter (on_x_event_filter_too, (gpointer)texture);
|
||||
}
|
||||
|
||||
g_object_ref (texture);
|
||||
g_object_notify (G_OBJECT (texture), "window");
|
||||
g_object_unref (texture);
|
||||
|
||||
clutter_x11_texture_pixmap_set_mapped (texture,
|
||||
attr.map_state == IsViewable);
|
||||
|
||||
clutter_x11_texture_pixmap_sync_window (texture);
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1026,34 +1183,102 @@ void
|
||||
clutter_x11_texture_pixmap_sync_window (ClutterX11TexturePixmap *texture)
|
||||
{
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
Pixmap pixmap, prev_pixmap;
|
||||
Pixmap pixmap;
|
||||
|
||||
g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture));
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
if (priv->destroyed)
|
||||
return;
|
||||
|
||||
if (!clutter_x11_has_composite_extension())
|
||||
{
|
||||
clutter_x11_texture_pixmap_set_pixmap (texture, priv->window);
|
||||
return;
|
||||
}
|
||||
|
||||
/* we own the pixmap */
|
||||
prev_pixmap = priv->pixmap;
|
||||
|
||||
if (priv->window)
|
||||
{
|
||||
XWindowAttributes attr;
|
||||
Display *dpy = clutter_x11_get_default_display ();
|
||||
gboolean mapped, notify_x, notify_y, notify_override_redirect;
|
||||
|
||||
/*
|
||||
* Make sure the window is mapped when getting the pixmap -- it's what
|
||||
* compiz does.
|
||||
*/
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
XGrabServer (dpy);
|
||||
|
||||
XGetWindowAttributes (dpy, priv->window, &attr);
|
||||
mapped = attr.map_state == IsViewable;
|
||||
if (mapped)
|
||||
pixmap = XCompositeNameWindowPixmap (dpy, priv->window);
|
||||
else
|
||||
pixmap = None;
|
||||
|
||||
XUngrabServer (dpy);
|
||||
clutter_x11_untrap_x_errors ();
|
||||
|
||||
clutter_x11_texture_pixmap_set_pixmap (texture, pixmap);
|
||||
notify_x = attr.x != priv->window_x;
|
||||
notify_y = attr.y != priv->window_y;
|
||||
notify_override_redirect = attr.override_redirect != priv->override_redirect;
|
||||
priv->window_x = attr.x;
|
||||
priv->window_y = attr.y;
|
||||
priv->override_redirect = attr.override_redirect;
|
||||
|
||||
if (prev_pixmap)
|
||||
XFreePixmap (dpy, prev_pixmap);
|
||||
g_object_ref (texture); /* guard against unparent */
|
||||
if (pixmap)
|
||||
{
|
||||
clutter_x11_texture_pixmap_set_pixmap (texture, pixmap);
|
||||
priv->owns_pixmap = TRUE;
|
||||
}
|
||||
clutter_x11_texture_pixmap_set_mapped (texture, mapped);
|
||||
/* could do more clever things with a signal, i guess.. */
|
||||
if (notify_override_redirect)
|
||||
g_object_notify (G_OBJECT (texture), "window-override-redirect");
|
||||
if (notify_x)
|
||||
g_object_notify (G_OBJECT (texture), "window-x");
|
||||
if (notify_y)
|
||||
g_object_notify (G_OBJECT (texture), "window-y");
|
||||
g_object_unref (texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_x11_texture_pixmap_set_mapped (ClutterX11TexturePixmap *texture,
|
||||
gboolean mapped)
|
||||
{
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
if (mapped != priv->window_mapped)
|
||||
{
|
||||
priv->window_mapped = mapped;
|
||||
g_object_notify (G_OBJECT (texture), "window-mapped");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_x11_texture_pixmap_destroyed (ClutterX11TexturePixmap *texture)
|
||||
{
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
if (!priv->destroyed)
|
||||
{
|
||||
priv->destroyed = TRUE;
|
||||
g_object_notify (G_OBJECT (texture), "destroyed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't set window to None, that would destroy the pixmap, which might still
|
||||
* be useful e.g. for destroy animations -- app's responsibility.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user