2009-06-26 15:33:20 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
2009-06-29 14:30:26 -04:00
|
|
|
#define _ISOC99_SOURCE /* for roundf */
|
|
|
|
#include <math.h>
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
#include <X11/extensions/shape.h>
|
|
|
|
#include <X11/extensions/Xcomposite.h>
|
|
|
|
#include <X11/extensions/Xdamage.h>
|
|
|
|
#include <X11/extensions/Xrender.h>
|
|
|
|
|
|
|
|
#include <clutter/x11/clutter-x11.h>
|
|
|
|
|
|
|
|
#include "../core/window-private.h" /* FIXME: add meta_window_is_override_redirect */
|
|
|
|
#include "display.h"
|
|
|
|
#include "errors.h"
|
|
|
|
#include "frame.h"
|
|
|
|
#include "window.h"
|
|
|
|
#include "xprops.h"
|
|
|
|
|
|
|
|
#include "compositor-private.h"
|
|
|
|
#include "mutter-shaped-texture.h"
|
|
|
|
#include "mutter-window-private.h"
|
|
|
|
#include "shadow.h"
|
2009-06-29 14:30:26 -04:00
|
|
|
#include "tidy/tidy-texture-frame.h"
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
struct _MutterWindowPrivate
|
|
|
|
{
|
|
|
|
XWindowAttributes attrs;
|
|
|
|
|
|
|
|
MetaWindow *window;
|
|
|
|
Window xwindow;
|
|
|
|
MetaScreen *screen;
|
|
|
|
|
|
|
|
ClutterActor *actor;
|
|
|
|
ClutterActor *shadow;
|
|
|
|
Pixmap back_pixmap;
|
|
|
|
|
|
|
|
MetaCompWindowType type;
|
|
|
|
Damage damage;
|
|
|
|
|
|
|
|
guint8 opacity;
|
|
|
|
|
|
|
|
gchar * desc;
|
|
|
|
|
2009-06-29 14:30:26 -04:00
|
|
|
/* If the window is shaped, a region that matches the shape */
|
|
|
|
GdkRegion *shape_region;
|
|
|
|
/* A rectangular region with the unshaped extends of the window
|
|
|
|
* texture */
|
|
|
|
GdkRegion *bounding_region;
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
/*
|
|
|
|
* These need to be counters rather than flags, since more plugins
|
|
|
|
* can implement same effect; the practicality of stacking effects
|
|
|
|
* might be dubious, but we have to at least handle it correctly.
|
|
|
|
*/
|
|
|
|
gint minimize_in_progress;
|
|
|
|
gint maximize_in_progress;
|
|
|
|
gint unmaximize_in_progress;
|
|
|
|
gint map_in_progress;
|
|
|
|
gint destroy_in_progress;
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
guint visible : 1;
|
|
|
|
guint mapped : 1;
|
2009-06-26 15:33:20 -04:00
|
|
|
guint shaped : 1;
|
|
|
|
guint argb32 : 1;
|
|
|
|
guint disposed : 1;
|
|
|
|
guint redecorating : 1;
|
|
|
|
|
|
|
|
guint needs_repair : 1;
|
2009-06-28 12:26:23 -04:00
|
|
|
guint needs_reshape : 1;
|
|
|
|
guint size_changed : 1;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
guint needs_destroy : 1;
|
|
|
|
|
|
|
|
guint no_shadow : 1;
|
|
|
|
|
|
|
|
guint no_more_x_calls : 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_MCW_META_WINDOW = 1,
|
|
|
|
PROP_MCW_META_SCREEN,
|
|
|
|
PROP_MCW_X_WINDOW,
|
|
|
|
PROP_MCW_X_WINDOW_ATTRIBUTES,
|
|
|
|
PROP_MCW_NO_SHADOW,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void mutter_window_dispose (GObject *object);
|
|
|
|
static void mutter_window_finalize (GObject *object);
|
|
|
|
static void mutter_window_constructed (GObject *object);
|
|
|
|
static void mutter_window_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void mutter_window_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
|
|
|
|
static void mutter_window_detach (MutterWindow *self);
|
|
|
|
static gboolean mutter_window_has_shadow (MutterWindow *self);
|
|
|
|
|
2009-06-29 14:30:26 -04:00
|
|
|
static void mutter_window_clear_shape_region (MutterWindow *self);
|
|
|
|
static void mutter_window_clear_bounding_region (MutterWindow *self);
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
static gboolean is_shaped (MetaDisplay *display,
|
|
|
|
Window xwindow);
|
|
|
|
/*
|
|
|
|
* Register GType wrapper for XWindowAttributes, so we do not have to
|
|
|
|
* query window attributes in the MutterWindow constructor but can pass
|
|
|
|
* them as a property to the constructor (so we can gracefully handle the case
|
|
|
|
* where no attributes can be retrieved).
|
|
|
|
*
|
|
|
|
* NB -- we only need a subset of the attributes; at some point we might want
|
|
|
|
* to just store the relevant values rather than the whole struct.
|
|
|
|
*/
|
|
|
|
#define META_TYPE_XATTRS (meta_xattrs_get_type ())
|
|
|
|
|
|
|
|
static GType meta_xattrs_get_type (void) G_GNUC_CONST;
|
|
|
|
|
|
|
|
static XWindowAttributes *
|
|
|
|
meta_xattrs_copy (const XWindowAttributes *attrs)
|
|
|
|
{
|
|
|
|
XWindowAttributes *result;
|
|
|
|
|
|
|
|
g_return_val_if_fail (attrs != NULL, NULL);
|
|
|
|
|
|
|
|
result = (XWindowAttributes*) g_malloc (sizeof (XWindowAttributes));
|
|
|
|
*result = *attrs;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_xattrs_free (XWindowAttributes *attrs)
|
|
|
|
{
|
|
|
|
g_return_if_fail (attrs != NULL);
|
|
|
|
|
|
|
|
g_free (attrs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GType
|
|
|
|
meta_xattrs_get_type (void)
|
|
|
|
{
|
|
|
|
static GType our_type = 0;
|
|
|
|
|
|
|
|
if (!our_type)
|
|
|
|
our_type = g_boxed_type_register_static ("XWindowAttributes",
|
|
|
|
(GBoxedCopyFunc) meta_xattrs_copy,
|
|
|
|
(GBoxedFreeFunc) meta_xattrs_free);
|
|
|
|
return our_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MutterWindow, mutter_window, CLUTTER_TYPE_GROUP);
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_class_init (MutterWindowClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
GParamSpec *pspec;
|
|
|
|
|
|
|
|
g_type_class_add_private (klass, sizeof (MutterWindowPrivate));
|
|
|
|
|
|
|
|
object_class->dispose = mutter_window_dispose;
|
|
|
|
object_class->finalize = mutter_window_finalize;
|
|
|
|
object_class->set_property = mutter_window_set_property;
|
|
|
|
object_class->get_property = mutter_window_get_property;
|
|
|
|
object_class->constructed = mutter_window_constructed;
|
|
|
|
|
|
|
|
pspec = g_param_spec_object ("meta-window",
|
|
|
|
"MetaWindow",
|
|
|
|
"The displayed MetaWindow",
|
|
|
|
META_TYPE_WINDOW,
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
PROP_MCW_META_WINDOW,
|
|
|
|
pspec);
|
|
|
|
|
|
|
|
pspec = g_param_spec_pointer ("meta-screen",
|
|
|
|
"MetaScreen",
|
|
|
|
"MetaScreen",
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
PROP_MCW_META_SCREEN,
|
|
|
|
pspec);
|
|
|
|
|
|
|
|
pspec = g_param_spec_ulong ("x-window",
|
|
|
|
"Window",
|
|
|
|
"Window",
|
|
|
|
0,
|
|
|
|
G_MAXULONG,
|
|
|
|
0,
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
PROP_MCW_X_WINDOW,
|
|
|
|
pspec);
|
|
|
|
|
|
|
|
pspec = g_param_spec_boxed ("x-window-attributes",
|
|
|
|
"XWindowAttributes",
|
|
|
|
"XWindowAttributes",
|
|
|
|
META_TYPE_XATTRS,
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
PROP_MCW_X_WINDOW_ATTRIBUTES,
|
|
|
|
pspec);
|
|
|
|
|
|
|
|
pspec = g_param_spec_boolean ("no-shadow",
|
|
|
|
"No shadow",
|
|
|
|
"Do not add shaddow to this window",
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class,
|
|
|
|
PROP_MCW_NO_SHADOW,
|
|
|
|
pspec);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_init (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv;
|
|
|
|
|
|
|
|
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
|
|
|
MUTTER_TYPE_COMP_WINDOW,
|
|
|
|
MutterWindowPrivate);
|
|
|
|
priv->opacity = 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_meta_window_decorated_notify (MetaWindow *mw,
|
|
|
|
GParamSpec *arg1,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
MutterWindow *self = MUTTER_WINDOW (data);
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
MetaFrame *frame = meta_window_get_frame (mw);
|
|
|
|
MetaScreen *screen = priv->screen;
|
|
|
|
MetaDisplay *display = meta_screen_get_display (screen);
|
|
|
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
|
|
|
Window new_xwindow;
|
|
|
|
MetaCompScreen *info;
|
|
|
|
XWindowAttributes attrs;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Basically, we have to reconstruct the the internals of this object
|
|
|
|
* from scratch, as everything has changed.
|
|
|
|
*/
|
|
|
|
priv->redecorating = TRUE;
|
|
|
|
|
|
|
|
if (frame)
|
|
|
|
new_xwindow = meta_frame_get_xwindow (frame);
|
|
|
|
else
|
|
|
|
new_xwindow = meta_window_get_xwindow (mw);
|
|
|
|
|
|
|
|
mutter_window_detach (self);
|
|
|
|
|
|
|
|
info = meta_screen_get_compositor_data (screen);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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, FALSE);
|
|
|
|
priv->damage = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
|
|
|
|
g_hash_table_insert (info->windows_by_xid, (gpointer) new_xwindow, self);
|
|
|
|
|
|
|
|
g_free (priv->desc);
|
|
|
|
priv->desc = NULL;
|
|
|
|
|
|
|
|
priv->xwindow = new_xwindow;
|
|
|
|
|
|
|
|
if (!XGetWindowAttributes (xdisplay, new_xwindow, &attrs))
|
|
|
|
{
|
|
|
|
g_warning ("Could not obtain attributes for window 0x%x after "
|
|
|
|
"decoration change",
|
|
|
|
(guint) new_xwindow);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_set (self, "x-window-attributes", &attrs, NULL);
|
|
|
|
|
|
|
|
if (priv->shadow)
|
|
|
|
{
|
|
|
|
ClutterActor *p = clutter_actor_get_parent (priv->shadow);
|
|
|
|
|
|
|
|
if (CLUTTER_IS_CONTAINER (p))
|
|
|
|
clutter_container_remove_actor (CLUTTER_CONTAINER (p), priv->shadow);
|
|
|
|
else
|
|
|
|
clutter_actor_unparent (priv->shadow);
|
|
|
|
|
|
|
|
priv->shadow = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Recreate the contents.
|
|
|
|
*/
|
|
|
|
mutter_window_constructed (G_OBJECT (self));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_constructed (GObject *object)
|
|
|
|
{
|
|
|
|
MutterWindow *self = MUTTER_WINDOW (object);
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
MetaScreen *screen = priv->screen;
|
|
|
|
MetaDisplay *display = meta_screen_get_display (screen);
|
|
|
|
Window xwindow = priv->xwindow;
|
|
|
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
|
|
|
XRenderPictFormat *format;
|
|
|
|
MetaCompositor *compositor;
|
|
|
|
|
|
|
|
compositor = meta_display_get_compositor (display);
|
|
|
|
|
|
|
|
mutter_window_update_window_type (self);
|
|
|
|
|
|
|
|
#ifdef HAVE_SHAPE
|
|
|
|
/* Listen for ShapeNotify events on the window */
|
|
|
|
if (meta_display_has_shape (display))
|
|
|
|
XShapeSelectInput (xdisplay, xwindow, ShapeNotifyMask);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
priv->shaped = is_shaped (display, xwindow);
|
|
|
|
|
|
|
|
if (priv->attrs.class == InputOnly)
|
|
|
|
priv->damage = None;
|
|
|
|
else
|
|
|
|
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportNonEmpty);
|
|
|
|
|
|
|
|
format = XRenderFindVisualFormat (xdisplay, priv->attrs.visual);
|
|
|
|
|
|
|
|
if (format && format->type == PictTypeDirect && format->direct.alphaMask)
|
|
|
|
priv->argb32 = TRUE;
|
|
|
|
|
|
|
|
mutter_window_update_opacity (self);
|
|
|
|
|
|
|
|
if (mutter_window_has_shadow (self))
|
|
|
|
{
|
|
|
|
priv->shadow = mutter_create_shadow_frame (compositor);
|
|
|
|
|
|
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!priv->actor)
|
|
|
|
{
|
|
|
|
priv->actor = mutter_shaped_texture_new ();
|
|
|
|
|
|
|
|
if (!clutter_glx_texture_pixmap_using_extension (
|
|
|
|
CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
|
|
|
|
g_warning ("NOTE: Not using GLX TFP!\n");
|
|
|
|
|
|
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor);
|
|
|
|
|
|
|
|
g_signal_connect (priv->window, "notify::decorated",
|
|
|
|
G_CALLBACK (mutter_meta_window_decorated_notify), self);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This is the case where existing window is gaining/loosing frame.
|
|
|
|
* Just ensure the actor is top most (i.e., above shadow).
|
|
|
|
*/
|
|
|
|
clutter_actor_raise_top (priv->actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mutter_window_update_shape (self, priv->shaped);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
MutterWindow *self = MUTTER_WINDOW (object);
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
MetaScreen *screen;
|
|
|
|
MetaDisplay *display;
|
|
|
|
Display *xdisplay;
|
|
|
|
MetaCompScreen *info;
|
|
|
|
|
|
|
|
if (priv->disposed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
priv->disposed = TRUE;
|
|
|
|
|
|
|
|
screen = priv->screen;
|
|
|
|
display = meta_screen_get_display (screen);
|
|
|
|
xdisplay = meta_display_get_xdisplay (display);
|
|
|
|
info = meta_screen_get_compositor_data (screen);
|
|
|
|
|
|
|
|
mutter_window_detach (self);
|
|
|
|
|
2009-06-29 14:30:26 -04:00
|
|
|
mutter_window_clear_shape_region (self);
|
|
|
|
mutter_window_clear_bounding_region (self);
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
if (priv->damage != None)
|
|
|
|
{
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
XDamageDestroy (xdisplay, priv->damage);
|
|
|
|
meta_error_trap_pop (display, FALSE);
|
|
|
|
|
|
|
|
priv->damage = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->windows = g_list_remove (info->windows, (gconstpointer) self);
|
|
|
|
g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (mutter_window_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_finalize (GObject *object)
|
|
|
|
{
|
2009-08-07 11:47:43 -04:00
|
|
|
MutterWindow *self = MUTTER_WINDOW (object);
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
g_free (priv->desc);
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
G_OBJECT_CLASS (mutter_window_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MutterWindow *self = MUTTER_WINDOW (object);
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_MCW_META_WINDOW:
|
|
|
|
priv->window = g_value_get_object (value);
|
|
|
|
break;
|
|
|
|
case PROP_MCW_META_SCREEN:
|
|
|
|
priv->screen = g_value_get_pointer (value);
|
|
|
|
break;
|
|
|
|
case PROP_MCW_X_WINDOW:
|
|
|
|
priv->xwindow = g_value_get_ulong (value);
|
|
|
|
break;
|
|
|
|
case PROP_MCW_X_WINDOW_ATTRIBUTES:
|
|
|
|
priv->attrs = *((XWindowAttributes*)g_value_get_boxed (value));
|
|
|
|
break;
|
|
|
|
case PROP_MCW_NO_SHADOW:
|
|
|
|
{
|
|
|
|
gboolean oldv = priv->no_shadow ? TRUE : FALSE;
|
|
|
|
gboolean newv = g_value_get_boolean (value);
|
|
|
|
|
|
|
|
if (oldv == newv)
|
|
|
|
return;
|
|
|
|
|
|
|
|
priv->no_shadow = newv;
|
|
|
|
|
|
|
|
if (newv && priv->shadow)
|
|
|
|
{
|
|
|
|
clutter_container_remove_actor (CLUTTER_CONTAINER (object),
|
|
|
|
priv->shadow);
|
|
|
|
priv->shadow = NULL;
|
|
|
|
}
|
|
|
|
else if (!newv && !priv->shadow && mutter_window_has_shadow (self))
|
|
|
|
{
|
|
|
|
gfloat w, h;
|
|
|
|
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
|
|
|
MetaCompositor *compositor;
|
|
|
|
|
|
|
|
compositor = meta_display_get_compositor (display);
|
|
|
|
|
|
|
|
clutter_actor_get_size (CLUTTER_ACTOR (self), &w, &h);
|
|
|
|
|
|
|
|
priv->shadow = mutter_create_shadow_frame (compositor);
|
|
|
|
|
|
|
|
clutter_actor_set_size (priv->shadow, w, h);
|
|
|
|
|
|
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = MUTTER_WINDOW (object)->priv;
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_MCW_META_WINDOW:
|
|
|
|
g_value_set_object (value, priv->window);
|
|
|
|
break;
|
|
|
|
case PROP_MCW_META_SCREEN:
|
|
|
|
g_value_set_pointer (value, priv->screen);
|
|
|
|
break;
|
|
|
|
case PROP_MCW_X_WINDOW:
|
|
|
|
g_value_set_ulong (value, priv->xwindow);
|
|
|
|
break;
|
|
|
|
case PROP_MCW_X_WINDOW_ATTRIBUTES:
|
|
|
|
g_value_set_boxed (value, &priv->attrs);
|
|
|
|
break;
|
|
|
|
case PROP_MCW_NO_SHADOW:
|
|
|
|
g_value_set_boolean (value, priv->no_shadow);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_update_window_type (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
priv->type = (MetaCompWindowType) meta_window_get_window_type (priv->window);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
is_shaped (MetaDisplay *display, Window xwindow)
|
|
|
|
{
|
|
|
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
|
|
|
gint xws, yws, xbs, ybs;
|
|
|
|
guint wws, hws, wbs, hbs;
|
|
|
|
gint bounding_shaped, clip_shaped;
|
|
|
|
|
|
|
|
if (meta_display_has_shape (display))
|
|
|
|
{
|
|
|
|
XShapeQueryExtents (xdisplay, xwindow, &bounding_shaped,
|
|
|
|
&xws, &yws, &wws, &hws, &clip_shaped,
|
|
|
|
&xbs, &ybs, &wbs, &hbs);
|
|
|
|
return (bounding_shaped != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
mutter_window_has_shadow (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate * priv = self->priv;
|
|
|
|
|
|
|
|
if (priv->no_shadow)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Always put a shadow around windows with a frame - This should override
|
|
|
|
* the restriction about not putting a shadow around shaped windows
|
|
|
|
* as the frame might be the reason the window is shaped
|
|
|
|
*/
|
|
|
|
if (priv->window)
|
|
|
|
{
|
|
|
|
if (meta_window_get_frame (priv->window))
|
|
|
|
{
|
|
|
|
meta_verbose ("Window 0x%x has shadow because it has a frame\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do not add shadows to ARGB windows (since they are probably transparent)
|
|
|
|
*/
|
|
|
|
if (priv->argb32 || priv->opacity != 0xff)
|
|
|
|
{
|
|
|
|
meta_verbose ("Window 0x%x has no shadow as it is ARGB\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Never put a shadow around shaped windows
|
|
|
|
*/
|
|
|
|
if (priv->shaped)
|
|
|
|
{
|
|
|
|
meta_verbose ("Window 0x%x has no shadow as it is shaped\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add shadows to override redirect windows (e.g., Gtk menus).
|
|
|
|
* This must have lower priority than window shape test.
|
|
|
|
*/
|
|
|
|
if (priv->attrs.override_redirect)
|
|
|
|
{
|
|
|
|
meta_verbose ("Window 0x%x has shadow because it is override redirect.\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't put shadow around DND icon windows
|
|
|
|
*/
|
|
|
|
if (priv->type == META_COMP_WINDOW_DND ||
|
|
|
|
priv->type == META_COMP_WINDOW_DESKTOP)
|
|
|
|
{
|
|
|
|
meta_verbose ("Window 0x%x has no shadow as it is DND or Desktop\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->type == META_COMP_WINDOW_MENU
|
|
|
|
#if 0
|
|
|
|
|| priv->type == META_COMP_WINDOW_DROPDOWN_MENU
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
meta_verbose ("Window 0x%x has shadow as it is a menu\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (priv->type == META_COMP_WINDOW_TOOLTIP)
|
|
|
|
{
|
|
|
|
meta_verbose ("Window 0x%x has shadow as it is a tooltip\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
meta_verbose ("Window 0x%x has no shadow as it fell through\n",
|
|
|
|
(guint)priv->xwindow);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window
|
|
|
|
mutter_window_get_x_window (MutterWindow *self)
|
|
|
|
{
|
|
|
|
if (!self)
|
|
|
|
return None;
|
|
|
|
|
|
|
|
return self->priv->xwindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mutter_window_get_meta_window:
|
|
|
|
*
|
|
|
|
* Gets the MetaWindow object that the the MutterWindow is displaying
|
|
|
|
*
|
|
|
|
* Return value: (transfer none): the displayed MetaWindow
|
|
|
|
*/
|
|
|
|
MetaWindow *
|
|
|
|
mutter_window_get_meta_window (MutterWindow *self)
|
|
|
|
{
|
|
|
|
return self->priv->window;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mutter_window_get_texture:
|
|
|
|
*
|
|
|
|
* Gets the ClutterActor that is used to display the contents of the window
|
|
|
|
*
|
|
|
|
* Return value: (transfer none): the ClutterActor for the contents
|
|
|
|
*/
|
|
|
|
ClutterActor *
|
|
|
|
mutter_window_get_texture (MutterWindow *self)
|
|
|
|
{
|
|
|
|
return self->priv->actor;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaCompWindowType
|
|
|
|
mutter_window_get_window_type (MutterWindow *self)
|
|
|
|
{
|
|
|
|
if (!self)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return self->priv->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
mutter_window_is_override_redirect (MutterWindow *self)
|
|
|
|
{
|
|
|
|
if (self->priv->window->override_redirect)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *mutter_window_get_description (MutterWindow *self)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* For windows managed by the WM, we just defer to the WM for the window
|
|
|
|
* description. For override-redirect windows, we create the description
|
|
|
|
* ourselves, but only on demand.
|
|
|
|
*/
|
|
|
|
if (self->priv->window)
|
|
|
|
return meta_window_get_description (self->priv->window);
|
|
|
|
|
|
|
|
if (G_UNLIKELY (self->priv->desc == NULL))
|
|
|
|
{
|
|
|
|
self->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
|
|
|
|
(guint) self->priv->xwindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
return self->priv->desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
mutter_window_get_workspace (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *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);
|
|
|
|
|
|
|
|
return meta_workspace_index (workspace);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
mutter_window_showing_on_its_workspace (MutterWindow *self)
|
|
|
|
{
|
|
|
|
if (!self)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* If override redirect: */
|
|
|
|
if (!self->priv->window)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return meta_window_showing_on_its_workspace (self->priv->window);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2009-06-28 15:06:58 -04:00
|
|
|
mutter_window_effect_in_progress (MutterWindow *self)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
return (self->priv->minimize_in_progress ||
|
|
|
|
self->priv->maximize_in_progress ||
|
|
|
|
self->priv->unmaximize_in_progress ||
|
|
|
|
self->priv->map_in_progress ||
|
2009-06-28 15:06:58 -04:00
|
|
|
self->priv->destroy_in_progress);
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
static void
|
|
|
|
mutter_window_mark_for_repair (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
priv->needs_repair = TRUE;
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
if (!priv->mapped)
|
2009-06-28 12:26:23 -04:00
|
|
|
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.
|
|
|
|
*/
|
2009-07-22 16:11:56 -04:00
|
|
|
clutter_actor_queue_redraw (priv->actor);
|
2009-06-28 12:26:23 -04:00
|
|
|
}
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
static gboolean
|
|
|
|
start_simple_effect (MutterWindow *self,
|
|
|
|
gulong event)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
|
|
|
|
gint *counter = NULL;
|
|
|
|
|
|
|
|
if (!info->plugin_mgr)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
switch (event)
|
|
|
|
{
|
|
|
|
case MUTTER_PLUGIN_MINIMIZE:
|
|
|
|
counter = &priv->minimize_in_progress;
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_MAP:
|
|
|
|
counter = &priv->map_in_progress;
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_DESTROY:
|
|
|
|
counter = &priv->destroy_in_progress;
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_UNMAXIMIZE:
|
|
|
|
case MUTTER_PLUGIN_MAXIMIZE:
|
|
|
|
case MUTTER_PLUGIN_SWITCH_WORKSPACE:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert (counter);
|
|
|
|
|
|
|
|
(*counter)++;
|
|
|
|
|
|
|
|
if (!mutter_plugin_manager_event_simple (info->plugin_mgr,
|
|
|
|
self,
|
|
|
|
event))
|
|
|
|
{
|
|
|
|
(*counter)--;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_after_effects (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
if (priv->needs_destroy)
|
|
|
|
{
|
|
|
|
clutter_actor_destroy (CLUTTER_ACTOR (self));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutter_window_sync_visibility (self);
|
|
|
|
mutter_window_sync_actor_position (self);
|
|
|
|
|
|
|
|
if (!priv->window->mapped)
|
|
|
|
mutter_window_detach (self);
|
|
|
|
|
|
|
|
if (priv->needs_repair)
|
2009-07-22 16:11:56 -04:00
|
|
|
clutter_actor_queue_redraw (priv->actor);
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
}
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
void
|
|
|
|
mutter_window_effect_completed (MutterWindow *self,
|
|
|
|
gulong event)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
/* NB: Keep in mind that when effects get completed it possible
|
|
|
|
* that the corresponding MetaWindow may have be been destroyed.
|
|
|
|
* In this case priv->window will == NULL */
|
|
|
|
|
|
|
|
switch (event)
|
|
|
|
{
|
|
|
|
case MUTTER_PLUGIN_MINIMIZE:
|
|
|
|
{
|
|
|
|
priv->minimize_in_progress--;
|
|
|
|
if (priv->minimize_in_progress < 0)
|
|
|
|
{
|
|
|
|
g_warning ("Error in minimize accounting.");
|
|
|
|
priv->minimize_in_progress = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_MAP:
|
|
|
|
/*
|
|
|
|
* Make sure that the actor is at the correct place in case
|
|
|
|
* the plugin fscked.
|
|
|
|
*/
|
|
|
|
priv->map_in_progress--;
|
|
|
|
|
|
|
|
if (priv->map_in_progress < 0)
|
|
|
|
{
|
|
|
|
g_warning ("Error in map accounting.");
|
|
|
|
priv->map_in_progress = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_DESTROY:
|
|
|
|
priv->destroy_in_progress--;
|
|
|
|
|
|
|
|
if (priv->destroy_in_progress < 0)
|
|
|
|
{
|
|
|
|
g_warning ("Error in destroy accounting.");
|
|
|
|
priv->destroy_in_progress = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_UNMAXIMIZE:
|
|
|
|
priv->unmaximize_in_progress--;
|
|
|
|
if (priv->unmaximize_in_progress < 0)
|
|
|
|
{
|
|
|
|
g_warning ("Error in unmaximize accounting.");
|
|
|
|
priv->unmaximize_in_progress = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_MAXIMIZE:
|
|
|
|
priv->maximize_in_progress--;
|
|
|
|
if (priv->maximize_in_progress < 0)
|
|
|
|
{
|
|
|
|
g_warning ("Error in maximize accounting.");
|
|
|
|
priv->maximize_in_progress = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MUTTER_PLUGIN_SWITCH_WORKSPACE:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
if (!mutter_window_effect_in_progress (self))
|
|
|
|
mutter_window_after_effects (self);
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
/* 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.
|
|
|
|
*/
|
2009-06-26 15:33:20 -04:00
|
|
|
static void
|
|
|
|
mutter_window_detach (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *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;
|
|
|
|
|
|
|
|
XFreePixmap (xdisplay, priv->back_pixmap);
|
|
|
|
priv->back_pixmap = None;
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
clutter_x11_texture_pixmap_set_pixmap (CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
|
|
|
|
None);
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
mutter_window_mark_for_repair (self);
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_destroy (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MetaWindow *window;
|
|
|
|
MetaCompScreen *info;
|
|
|
|
MutterWindowPrivate *priv;
|
|
|
|
|
|
|
|
priv = self->priv;
|
|
|
|
|
|
|
|
window = priv->window;
|
|
|
|
meta_window_set_compositor_private (window, NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We remove the window from internal lookup hashes and thus any other
|
|
|
|
* unmap events etc fail
|
|
|
|
*/
|
|
|
|
info = meta_screen_get_compositor_data (priv->screen);
|
|
|
|
info->windows = g_list_remove (info->windows, (gconstpointer) self);
|
|
|
|
g_hash_table_remove (info->windows_by_xid, (gpointer)priv->xwindow);
|
|
|
|
|
|
|
|
if (priv->type == META_COMP_WINDOW_DROPDOWN_MENU ||
|
|
|
|
priv->type == META_COMP_WINDOW_POPUP_MENU ||
|
|
|
|
priv->type == META_COMP_WINDOW_TOOLTIP ||
|
|
|
|
priv->type == META_COMP_WINDOW_NOTIFICATION ||
|
|
|
|
priv->type == META_COMP_WINDOW_COMBO ||
|
|
|
|
priv->type == META_COMP_WINDOW_DND ||
|
|
|
|
priv->type == META_COMP_WINDOW_OVERRIDE_OTHER)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* No effects, just kill it.
|
|
|
|
*/
|
|
|
|
clutter_actor_destroy (CLUTTER_ACTOR (self));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
priv->needs_destroy = TRUE;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Once the window destruction is initiated we can no longer perform any
|
|
|
|
* furter X-based operations. For example, if we have a Map effect running,
|
|
|
|
* we cannot query the window geometry once the effect completes. So, flag
|
|
|
|
* this.
|
|
|
|
*/
|
|
|
|
priv->no_more_x_calls = TRUE;
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
if (!mutter_window_effect_in_progress (self))
|
|
|
|
clutter_actor_destroy (CLUTTER_ACTOR (self));
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_sync_actor_position (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
MetaRectangle window_rect;
|
|
|
|
|
|
|
|
meta_window_get_outer_rect (priv->window, &window_rect);
|
|
|
|
|
|
|
|
if (priv->attrs.width != window_rect.width ||
|
|
|
|
priv->attrs.height != window_rect.height)
|
2009-06-28 12:26:23 -04:00
|
|
|
{
|
|
|
|
priv->size_changed = TRUE;
|
|
|
|
mutter_window_mark_for_repair (self);
|
|
|
|
}
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
/* XXX deprecated: please use meta_window_get_outer_rect instead */
|
|
|
|
priv->attrs.width = window_rect.width;
|
|
|
|
priv->attrs.height = window_rect.height;
|
|
|
|
priv->attrs.x = window_rect.x;
|
|
|
|
priv->attrs.y = window_rect.y;
|
|
|
|
|
2009-06-28 15:06:58 -04:00
|
|
|
if (mutter_window_effect_in_progress (self))
|
2009-06-26 15:33:20 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
clutter_actor_set_position (CLUTTER_ACTOR (self),
|
2009-06-28 12:26:23 -04:00
|
|
|
window_rect.x, window_rect.y);
|
|
|
|
clutter_actor_set_size (CLUTTER_ACTOR (self),
|
|
|
|
window_rect.width, window_rect.height);
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
mutter_window_show (MutterWindow *self,
|
|
|
|
MetaCompEffect effect)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv;
|
|
|
|
MetaCompScreen *info;
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
gulong event;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
priv = self->priv;
|
|
|
|
info = meta_screen_get_compositor_data (priv->screen);
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
g_return_if_fail (!priv->visible);
|
2009-06-26 15:33:20 -04:00
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
self->priv->visible = TRUE;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
event = 0;
|
|
|
|
switch (effect)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
case META_COMP_EFFECT_CREATE:
|
|
|
|
event = MUTTER_PLUGIN_MAP;
|
|
|
|
break;
|
|
|
|
case META_COMP_EFFECT_UNMINIMIZE:
|
|
|
|
/* FIXME: should have MUTTER_PLUGIN_UNMINIMIZE */
|
|
|
|
event = MUTTER_PLUGIN_MAP;
|
|
|
|
break;
|
|
|
|
case META_COMP_EFFECT_NONE:
|
|
|
|
break;
|
|
|
|
case META_COMP_EFFECT_DESTROY:
|
|
|
|
case META_COMP_EFFECT_MINIMIZE:
|
|
|
|
g_assert_not_reached();
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->redecorating ||
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
info->switch_workspace_in_progress ||
|
|
|
|
event == 0 ||
|
|
|
|
!start_simple_effect (self, event))
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
clutter_actor_show_all (CLUTTER_ACTOR (self));
|
|
|
|
priv->redecorating = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
mutter_window_hide (MutterWindow *self,
|
|
|
|
MetaCompEffect effect)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv;
|
|
|
|
MetaCompScreen *info;
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
gulong event;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
priv = self->priv;
|
|
|
|
info = meta_screen_get_compositor_data (priv->screen);
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
g_return_if_fail (priv->visible);
|
2009-06-26 15:33:20 -04:00
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
priv->visible = FALSE;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
/* If a plugin is animating a workspace transition, we have to
|
|
|
|
* hold off on hiding the window, and do it after the workspace
|
|
|
|
* switch completes
|
2009-06-26 15:33:20 -04:00
|
|
|
*/
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
if (info->switch_workspace_in_progress)
|
|
|
|
return;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
event = 0;
|
|
|
|
switch (effect)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
case META_COMP_EFFECT_DESTROY:
|
|
|
|
event = MUTTER_PLUGIN_DESTROY;
|
|
|
|
break;
|
|
|
|
case META_COMP_EFFECT_MINIMIZE:
|
|
|
|
event = MUTTER_PLUGIN_MINIMIZE;
|
|
|
|
break;
|
|
|
|
case META_COMP_EFFECT_NONE:
|
|
|
|
break;
|
|
|
|
case META_COMP_EFFECT_UNMINIMIZE:
|
|
|
|
case META_COMP_EFFECT_CREATE:
|
|
|
|
g_assert_not_reached();
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
|
|
|
|
if (event == 0 ||
|
|
|
|
!start_simple_effect (self, event))
|
|
|
|
clutter_actor_hide (CLUTTER_ACTOR (self));
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_maximize (MutterWindow *self,
|
2009-06-28 12:26:23 -04:00
|
|
|
MetaRectangle *old_rect,
|
|
|
|
MetaRectangle *new_rect)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
/* The window has already been resized (in order to compute new_rect),
|
|
|
|
* which by side effect caused the actor to be resized. Restore it to the
|
|
|
|
* old size and position */
|
|
|
|
clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
|
|
|
|
clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
self->priv->maximize_in_progress++;
|
|
|
|
|
|
|
|
if (!info->plugin_mgr ||
|
|
|
|
!mutter_plugin_manager_event_maximize (info->plugin_mgr,
|
|
|
|
self,
|
|
|
|
MUTTER_PLUGIN_MAXIMIZE,
|
2009-06-28 12:26:23 -04:00
|
|
|
new_rect->x, new_rect->y,
|
|
|
|
new_rect->width, new_rect->height))
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
{
|
|
|
|
self->priv->maximize_in_progress--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_unmaximize (MutterWindow *self,
|
2009-06-28 12:26:23 -04:00
|
|
|
MetaRectangle *old_rect,
|
|
|
|
MetaRectangle *new_rect)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
/* The window has already been resized (in order to compute new_rect),
|
|
|
|
* which by side effect caused the actor to be resized. Restore it to the
|
|
|
|
* old size and position */
|
|
|
|
clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
|
|
|
|
clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
self->priv->unmaximize_in_progress++;
|
|
|
|
|
|
|
|
if (!info->plugin_mgr ||
|
|
|
|
!mutter_plugin_manager_event_maximize (info->plugin_mgr,
|
|
|
|
self,
|
|
|
|
MUTTER_PLUGIN_UNMAXIMIZE,
|
2009-06-28 12:26:23 -04:00
|
|
|
new_rect->x, new_rect->y,
|
|
|
|
new_rect->width, new_rect->height))
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
self->priv->unmaximize_in_progress--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MutterWindow *
|
|
|
|
mutter_window_new (MetaWindow *window)
|
|
|
|
{
|
|
|
|
MetaScreen *screen = meta_window_get_screen (window);
|
|
|
|
MetaDisplay *display = meta_screen_get_display (screen);
|
|
|
|
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
|
|
|
MutterWindow *self;
|
|
|
|
MutterWindowPrivate *priv;
|
|
|
|
MetaFrame *frame;
|
|
|
|
Window top_window;
|
|
|
|
XWindowAttributes attrs;
|
|
|
|
|
|
|
|
frame = meta_window_get_frame (window);
|
|
|
|
if (frame)
|
|
|
|
top_window = meta_frame_get_xwindow (frame);
|
|
|
|
else
|
|
|
|
top_window = meta_window_get_xwindow (window);
|
|
|
|
|
|
|
|
meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
|
|
|
|
|
|
|
|
/* FIXME: Remove the redundant data we store in self->priv->attrs, and
|
|
|
|
* simply query metacity core for the data. */
|
|
|
|
if (!XGetWindowAttributes (display->xdisplay, top_window, &attrs))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
self = g_object_new (MUTTER_TYPE_COMP_WINDOW,
|
|
|
|
"meta-window", window,
|
|
|
|
"x-window", top_window,
|
|
|
|
"meta-screen", screen,
|
|
|
|
"x-window-attributes", &attrs,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
priv = self->priv;
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
priv->mapped = meta_window_toplevel_is_mapped (priv->window);
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
mutter_window_sync_actor_position (self);
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
/* Hang our compositor window state off the MetaWindow for fast retrieval */
|
|
|
|
meta_window_set_compositor_private (window, G_OBJECT (self));
|
|
|
|
|
|
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (info->window_group),
|
|
|
|
CLUTTER_ACTOR (self));
|
|
|
|
clutter_actor_hide (CLUTTER_ACTOR (self));
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
/* Initial position in the stack is arbitrary; stacking will be synced
|
|
|
|
* before we first paint.
|
2009-06-26 15:33:20 -04:00
|
|
|
*/
|
|
|
|
info->windows = g_list_append (info->windows, self);
|
|
|
|
g_hash_table_insert (info->windows_by_xid, (gpointer) top_window, self);
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
void
|
|
|
|
mutter_window_mapped (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
g_return_if_fail (!priv->mapped);
|
|
|
|
|
|
|
|
priv->mapped = TRUE;
|
|
|
|
|
|
|
|
mutter_window_mark_for_repair (self);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_unmapped (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
g_return_if_fail (priv->mapped);
|
|
|
|
|
|
|
|
priv->mapped = FALSE;
|
|
|
|
|
|
|
|
if (mutter_window_effect_in_progress (self))
|
|
|
|
return;
|
|
|
|
|
|
|
|
mutter_window_detach (self);
|
|
|
|
priv->needs_repair = FALSE;
|
|
|
|
}
|
|
|
|
|
2009-06-29 14:30:26 -04:00
|
|
|
static void
|
|
|
|
mutter_window_clear_shape_region (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
if (priv->shape_region)
|
|
|
|
{
|
|
|
|
gdk_region_destroy (priv->shape_region);
|
|
|
|
priv->shape_region = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_clear_bounding_region (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
if (priv->bounding_region)
|
|
|
|
{
|
|
|
|
gdk_region_destroy (priv->bounding_region);
|
|
|
|
priv->bounding_region = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_update_bounding_region (MutterWindow *self,
|
|
|
|
int width,
|
|
|
|
int height)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
GdkRectangle bounding_rectangle = { 0, 0, width, height };
|
|
|
|
|
|
|
|
mutter_window_clear_bounding_region (self);
|
|
|
|
|
|
|
|
priv->bounding_region = gdk_region_rectangle (&bounding_rectangle);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mutter_window_update_shape_region (MutterWindow *self,
|
|
|
|
int n_rects,
|
|
|
|
XRectangle *rects)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
mutter_window_clear_shape_region (self);
|
|
|
|
|
|
|
|
priv->shape_region = gdk_region_new ();
|
|
|
|
for (i = 0; i < n_rects; i++)
|
|
|
|
{
|
|
|
|
GdkRectangle rect = { rects[i].x, rects[i].y, rects[i].width, rects[i].height };
|
|
|
|
gdk_region_union_with_rect (priv->shape_region, &rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mutter_window_get_obscured_region:
|
|
|
|
* @self: a #MutterWindow
|
|
|
|
*
|
|
|
|
* Gets the region that is completely obscured by the window. Coordinates
|
|
|
|
* are relative to the upper-left of the window.
|
|
|
|
*
|
|
|
|
* Return value: (transfer none): the area obscured by the window,
|
|
|
|
* %NULL is the same as an empty region.
|
|
|
|
*/
|
|
|
|
GdkRegion *
|
|
|
|
mutter_window_get_obscured_region (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
if (!priv->argb32 && priv->back_pixmap)
|
|
|
|
{
|
|
|
|
if (priv->shaped)
|
|
|
|
return priv->shape_region;
|
|
|
|
else
|
|
|
|
return priv->bounding_region;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* Print out a region; useful for debugging */
|
|
|
|
static void
|
|
|
|
dump_region (GdkRegion *region)
|
|
|
|
{
|
|
|
|
GdkRectangle *rects;
|
|
|
|
int n_rects;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
gdk_region_get_rectangles (region, &rects, &n_rects);
|
|
|
|
g_print ("[");
|
|
|
|
for (i = 0; i < n_rects; i++)
|
|
|
|
{
|
|
|
|
g_print ("+%d+%dx%dx%d ",
|
|
|
|
rects[i].x, rects[i].y, rects[i].width, rects[i].height);
|
|
|
|
}
|
|
|
|
g_print ("]\n");
|
|
|
|
g_free (rects);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mutter_window_set_visible_region:
|
|
|
|
* @self: a #MutterWindow
|
|
|
|
* @visible_region: the region of the screen that isn't completely
|
|
|
|
* obscured.
|
|
|
|
*
|
|
|
|
* Provides a hint as to what areas of the window need to be
|
|
|
|
* drawn. Regions not in @visible_region are completely obscured.
|
|
|
|
* This will be set before painting then unset afterwards.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
mutter_window_set_visible_region (MutterWindow *self,
|
|
|
|
GdkRegion *visible_region)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
GdkRegion *texture_clip_region = NULL;
|
|
|
|
|
|
|
|
/* Get the area of the window texture that would be drawn if
|
|
|
|
* we weren't obscured at all
|
|
|
|
*/
|
|
|
|
if (priv->shaped)
|
|
|
|
{
|
|
|
|
if (priv->shape_region)
|
|
|
|
texture_clip_region = gdk_region_copy (priv->shape_region);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (priv->bounding_region)
|
|
|
|
texture_clip_region = gdk_region_copy (priv->bounding_region);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!texture_clip_region)
|
|
|
|
texture_clip_region = gdk_region_new ();
|
|
|
|
|
|
|
|
/* Then intersect that with the visible region to get the region
|
|
|
|
* that we actually need to redraw.
|
|
|
|
*/
|
|
|
|
gdk_region_intersect (texture_clip_region, visible_region);
|
|
|
|
|
|
|
|
/* Assumes ownership */
|
|
|
|
mutter_shaped_texture_set_clip_region (MUTTER_SHAPED_TEXTURE (priv->actor),
|
|
|
|
texture_clip_region);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mutter_window_set_visible_region_beneath:
|
|
|
|
* @self: a #MutterWindow
|
|
|
|
* @visible_region: the region of the screen that isn't completely
|
|
|
|
* obscured beneath the main window texture.
|
|
|
|
*
|
|
|
|
* Provides a hint as to what areas need to be drawn *beneath*
|
|
|
|
* the main window texture. This is the relevant visible region
|
|
|
|
* when drawing the shadow, properly accounting for areas of the
|
|
|
|
* shadow hid by the window itself. This will be set before painting
|
|
|
|
* then unset afterwards.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
mutter_window_set_visible_region_beneath (MutterWindow *self,
|
|
|
|
GdkRegion *beneath_region)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
if (priv->shadow)
|
|
|
|
{
|
|
|
|
GdkRectangle shadow_rect;
|
|
|
|
ClutterActorBox box;
|
|
|
|
GdkOverlapType overlap;
|
|
|
|
|
|
|
|
/* We could compute an full clip region as we do for the window
|
|
|
|
* texture, but the shadow is relatively cheap to draw, and
|
|
|
|
* a little more complex to clip, so we just catch the case where
|
|
|
|
* the shadow is completely obscured and doesn't need to be drawn
|
|
|
|
* at all.
|
|
|
|
*/
|
|
|
|
clutter_actor_get_allocation_box (priv->shadow, &box);
|
|
|
|
|
|
|
|
shadow_rect.x = roundf (box.x1);
|
|
|
|
shadow_rect.y = roundf (box.y1);
|
|
|
|
shadow_rect.width = roundf (box.x2 - box.x1);
|
|
|
|
shadow_rect.height = roundf (box.y2 - box.y1);
|
|
|
|
|
|
|
|
overlap = gdk_region_rect_in (beneath_region, &shadow_rect);
|
|
|
|
|
|
|
|
tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow),
|
|
|
|
overlap != GDK_OVERLAP_RECTANGLE_OUT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mutter_window_reset_visible_regions:
|
|
|
|
* @self: a #MutterWindow
|
|
|
|
*
|
|
|
|
* Unsets the regions set by mutter_window_reset_visible_region() and
|
|
|
|
*mutter_window_reset_visible_region_beneath()
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
mutter_window_reset_visible_regions (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
mutter_shaped_texture_set_clip_region (MUTTER_SHAPED_TEXTURE (priv->actor),
|
|
|
|
NULL);
|
|
|
|
if (priv->shadow)
|
|
|
|
tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow), TRUE);
|
|
|
|
}
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
static void
|
2009-06-28 12:26:23 -04:00
|
|
|
check_needs_repair (MutterWindow *self)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
MutterWindowPrivate *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);
|
|
|
|
MetaCompositor *compositor;
|
|
|
|
Window xwindow = priv->xwindow;
|
|
|
|
gboolean full = FALSE;
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
if (!priv->needs_repair)
|
|
|
|
return;
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
if (!priv->mapped)
|
2009-06-28 12:26:23 -04:00
|
|
|
return;
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
if (xwindow == meta_screen_get_xroot (screen) ||
|
|
|
|
xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
compositor = meta_display_get_compositor (display);
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
if (priv->size_changed)
|
|
|
|
{
|
|
|
|
mutter_window_detach (self);
|
|
|
|
priv->size_changed = FALSE;
|
|
|
|
}
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
meta_error_trap_push (display);
|
|
|
|
|
|
|
|
if (priv->back_pixmap == None)
|
|
|
|
{
|
|
|
|
gint pxm_width, pxm_height;
|
|
|
|
|
|
|
|
meta_error_trap_push (display);
|
|
|
|
|
|
|
|
priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
|
|
|
|
|
|
|
if (meta_error_trap_pop_with_return (display, FALSE) != 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);
|
2009-06-29 14:30:26 -04:00
|
|
|
mutter_window_update_bounding_region (self, 0, 0);
|
2009-06-26 15:33:20 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MUST call before setting pixmap or serious performance issues
|
|
|
|
* seemingly caused by cogl_texture_set_filters() in set_filter
|
|
|
|
* Not sure if that call is actually needed.
|
|
|
|
*/
|
|
|
|
if (!compositor->no_mipmaps)
|
|
|
|
clutter_texture_set_filter_quality (CLUTTER_TEXTURE (priv->actor),
|
|
|
|
CLUTTER_TEXTURE_QUALITY_HIGH );
|
|
|
|
|
|
|
|
clutter_x11_texture_pixmap_set_pixmap
|
|
|
|
(CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
|
|
|
|
priv->back_pixmap);
|
|
|
|
|
|
|
|
g_object_get (priv->actor,
|
|
|
|
"pixmap-width", &pxm_width,
|
|
|
|
"pixmap-height", &pxm_height,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (priv->shadow)
|
|
|
|
clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
|
|
|
|
|
2009-06-29 14:30:26 -04:00
|
|
|
mutter_window_update_bounding_region (self, pxm_width, pxm_height);
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
full = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO -- on some gfx hardware updating the whole texture instead of
|
|
|
|
* the individual rectangles is actually quicker, so we might want to
|
|
|
|
* make this a configurable option (on desktop HW with multiple pipelines
|
|
|
|
* it is usually quicker to just update the damaged parts).
|
|
|
|
*
|
|
|
|
* If we are using TFP we update the whole texture (this simply trigers
|
|
|
|
* the texture rebind).
|
|
|
|
*/
|
|
|
|
if (full
|
|
|
|
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
|
|
|
|| (CLUTTER_GLX_IS_TEXTURE_PIXMAP (priv->actor) &&
|
|
|
|
clutter_glx_texture_pixmap_using_extension
|
|
|
|
(CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
|
|
|
|
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
XDamageSubtract (xdisplay, priv->damage, None, None);
|
|
|
|
|
|
|
|
clutter_x11_texture_pixmap_update_area
|
|
|
|
(CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
clutter_actor_get_width (priv->actor),
|
|
|
|
clutter_actor_get_height (priv->actor));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
XRectangle *r_damage;
|
|
|
|
XRectangle r_bounds;
|
|
|
|
XserverRegion parts;
|
|
|
|
int i, r_count;
|
|
|
|
|
|
|
|
parts = XFixesCreateRegion (xdisplay, 0, 0);
|
|
|
|
XDamageSubtract (xdisplay, priv->damage, None, parts);
|
|
|
|
|
|
|
|
r_damage = XFixesFetchRegionAndBounds (xdisplay,
|
|
|
|
parts,
|
|
|
|
&r_count,
|
|
|
|
&r_bounds);
|
|
|
|
|
|
|
|
if (r_damage)
|
|
|
|
{
|
|
|
|
for (i = 0; i < r_count; ++i)
|
|
|
|
{
|
|
|
|
clutter_x11_texture_pixmap_update_area
|
|
|
|
(CLUTTER_X11_TEXTURE_PIXMAP (priv->actor),
|
|
|
|
r_damage[i].x,
|
|
|
|
r_damage[i].y,
|
|
|
|
r_damage[i].width,
|
|
|
|
r_damage[i].height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree (r_damage);
|
|
|
|
XFixesDestroyRegion (xdisplay, parts);
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_error_trap_pop (display, FALSE);
|
|
|
|
|
|
|
|
priv->needs_repair = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_process_damage (MutterWindow *self,
|
|
|
|
XDamageNotifyEvent *event)
|
|
|
|
{
|
2009-06-28 12:26:23 -04:00
|
|
|
mutter_window_mark_for_repair (self);
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
mutter_window_sync_visibility (MutterWindow *self)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self) != priv->visible)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
Simplify relationship between mapping and visibility
Previously, changes to the visibility of a window could be indicated
by meta_compositor_map_window(), meta_compositor_unminimize_window(),
meta_compositor_set_window_hidden(), etc, with the exact behavior
depending on the 'live_hidden_windows' preference.
Simplify this so that visibility is controlled by:
meta_compositor_show_window()
meta_compositor_hide_window()
With an 'effect' parameter provided to indicate the appropriate
effect (CREATE/UNMINIMIZE/MINIMIZE/DESTROY/NONE.)
The map state of the window is signalled separately by:
meta_compositor_map_window()
meta_compositor_unmap_window()
And is used only to control resource handling.
Other changes:
* The desired effect on show/hide is explicitly stored in
MetaWindow, avoiding the need for the was_minimized flag.
At idle, once we calculate the window state, we pass the
effect to the compositor if it matches the new window
state, and then clear the effect to start over for future
map state changes.
* meta_compositor_switch_workspace() is called before any windows
are hidden or shown, allowing the compositor to avoid hiding
or showing an effect for windows involved in the switch.
http://bugzilla.gnome.org/show_bug.cgi?id=582341
* Handling of post-effect cleanups for MutterWindow are
simplified - instead of trying to do different things based
on the individual needs of different effects, we just wait until
all effects complete and sync the window state to what it
should be.
* On unmap, once we destroy the pixmap, we tell ClutterX11Pixmap
that we've done so, so it can clean up and unbind. (The
unbinding doesn't seem to be working properly because of
ClutterGLXPixmap or video driver issues.)
http://bugzilla.gnome.org/show_bug.cgi?id=587251
2009-06-28 17:10:40 -04:00
|
|
|
if (priv->visible)
|
|
|
|
clutter_actor_show (CLUTTER_ACTOR (self));
|
|
|
|
else
|
|
|
|
clutter_actor_hide (CLUTTER_ACTOR (self));
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
static void
|
|
|
|
check_needs_reshape (MutterWindow *self)
|
2009-06-26 15:33:20 -04:00
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
2009-06-28 12:26:23 -04:00
|
|
|
if (!priv->needs_reshape)
|
|
|
|
return;
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
mutter_shaped_texture_clear_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor));
|
2009-06-29 14:30:26 -04:00
|
|
|
mutter_window_clear_shape_region (self);
|
2009-06-26 15:33:20 -04:00
|
|
|
|
|
|
|
#ifdef HAVE_SHAPE
|
|
|
|
if (priv->shaped)
|
|
|
|
{
|
|
|
|
Display *xdisplay = meta_display_get_xdisplay (priv->window->display);
|
|
|
|
XRectangle *rects;
|
|
|
|
int n_rects, ordering;
|
|
|
|
|
|
|
|
rects = XShapeGetRectangles (xdisplay,
|
|
|
|
priv->xwindow,
|
|
|
|
ShapeBounding,
|
|
|
|
&n_rects,
|
|
|
|
&ordering);
|
|
|
|
|
|
|
|
if (rects)
|
|
|
|
{
|
|
|
|
mutter_shaped_texture_add_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor),
|
|
|
|
n_rects, rects);
|
|
|
|
|
2009-06-29 14:30:26 -04:00
|
|
|
mutter_window_update_shape_region (self, n_rects, rects);
|
|
|
|
|
2009-06-26 15:33:20 -04:00
|
|
|
XFree (rects);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2009-06-28 12:26:23 -04:00
|
|
|
|
|
|
|
priv->needs_reshape = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_update_shape (MutterWindow *self,
|
|
|
|
gboolean shaped)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
priv->shaped = shaped;
|
|
|
|
priv->needs_reshape = TRUE;
|
|
|
|
|
2009-07-22 16:11:56 -04:00
|
|
|
clutter_actor_queue_redraw (priv->actor);
|
2009-06-28 12:26:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_pre_paint (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
/* The window is frozen due to a pending animation: we'll wait until
|
|
|
|
* the animation finishes to reshape and repair the window */
|
|
|
|
if (priv->destroy_in_progress ||
|
|
|
|
priv->maximize_in_progress ||
|
|
|
|
priv->unmaximize_in_progress)
|
|
|
|
return;
|
|
|
|
|
|
|
|
check_needs_reshape (self);
|
|
|
|
check_needs_repair (self);
|
2009-06-26 15:33:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mutter_window_update_opacity (MutterWindow *self)
|
|
|
|
{
|
|
|
|
MutterWindowPrivate *priv = self->priv;
|
|
|
|
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
|
|
|
MetaCompositor *compositor = meta_display_get_compositor (display);
|
|
|
|
Window xwin = meta_window_get_xwindow (priv->window);
|
|
|
|
gulong value;
|
|
|
|
guint8 opacity;
|
|
|
|
|
|
|
|
if (meta_prop_get_cardinal (display, xwin,
|
|
|
|
compositor->atom_net_wm_window_opacity,
|
|
|
|
&value))
|
|
|
|
{
|
|
|
|
opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
opacity = 255;
|
|
|
|
|
|
|
|
self->priv->opacity = opacity;
|
|
|
|
clutter_actor_set_opacity (CLUTTER_ACTOR (self), opacity);
|
|
|
|
}
|