[mutter] Separate source and header files for MutterWindow
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Subject: [mutter] Separate source and header files for MutterWindow
- Date: Mon, 6 Jul 2009 07:44:34 +0000 (UTC)
commit c60d4c2bc43d374269f3148bc752a48b6033376a
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Fri Jun 26 15:33:20 2009 -0400
Separate source and header files for MutterWindow
compositor.c: Move MutterWindow code to mutter-window.c;
rename map_win() to mutter_window_map(), etc.
mutter-window-private.h: New private header file for
MutterWindow functions used internally to the compositor.
compositor-mutter.h: Move MutterWindow declarations to
mutter-window.h; move a couple of private functions to
compositor-private.h
compositor-private.h: Move MetaCompScreen declaration to here:
Conceptually it's private to compositor.c, but MutterWindow
manipulates some of the lists directly for now.
mutter-plugin.c compositor.c: Don't call mutter_window_effect_completed()
for MUTTER_PLUGIN_SWITCH_WORKSPACE, but use a new
mutter_switch_workspace_completed(), since the window is
just used to identify a screen.
http://bugzilla.gnome.org/show_bug.cgi?id=587251
src/Makefile.am | 6 +-
src/compositor/compositor-private.h | 30 +
src/compositor/compositor.c | 1580 +-------------------------------
src/compositor/mutter-plugin.c | 15 +-
src/compositor/mutter-window-private.h | 39 +
src/compositor/mutter-window.c | 1528 ++++++++++++++++++++++++++++++
src/include/compositor-mutter.h | 50 +-
src/include/mutter-window.h | 71 ++
8 files changed, 1727 insertions(+), 1592 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index d46a73a..e3a7c5c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,8 @@ mutter_SOURCES= \
compositor/mutter-plugin-manager.c \
compositor/mutter-plugin-manager.h \
compositor/mutter-shaped-texture.c \
+ compositor/mutter-window.c \
+ compositor/mutter-window-private.h \
compositor/shadow.c \
compositor/shadow.h \
compositor/mutter-shaped-texture.h \
@@ -36,6 +38,7 @@ mutter_SOURCES= \
compositor/tidy/tidy-texture-frame.h \
include/compositor.h \
include/mutter-plugin.h \
+ include/mutter-window.h \
include/compositor-mutter.h \
core/constraints.c \
core/constraints.h \
@@ -162,7 +165,8 @@ libmutterinclude_base_headers = \
include/display.h \
include/group.h \
include/keybindings.h \
- include/mutter-plugin.h
+ include/mutter-plugin.h \
+ include/mutter-window.h
# Excluded from scanning for introspection but installed
libmutterinclude_extra_headers = \
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 6611761..986c570 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -3,10 +3,15 @@
#ifndef META_COMPOSITOR_PRIVATE_H
#define META_COMPOSITOR_PRIVATE_H
+#include <X11/extensions/Xfixes.h>
+
#include "compositor.h"
#include "display.h"
+#include "mutter-plugin-manager.h"
#include <clutter/clutter.h>
+typedef struct _MetaCompScreen MetaCompScreen;
+
struct _MetaCompositor
{
MetaDisplay *display;
@@ -22,4 +27,29 @@ struct _MetaCompositor
gboolean no_mipmaps : 1;
};
+struct _MetaCompScreen
+{
+ MetaScreen *screen;
+
+ ClutterActor *stage, *window_group, *overlay_group;
+ ClutterActor *hidden_group;
+ GList *windows;
+ GHashTable *windows_by_xid;
+ MetaWindow *focus_window;
+ Window output;
+ GSList *dock_windows;
+
+ /* Before we create the output window */
+ XserverRegion pending_input_region;
+
+ gint switch_workspace_in_progress;
+
+ MutterPluginManager *plugin_mgr;
+};
+
+void mutter_switch_workspace_completed (MetaScreen *screen);
+void mutter_set_stage_input_region (MetaScreen *screen,
+ XserverRegion region);
+void mutter_empty_stage_input_region (MetaScreen *screen);
+
#endif /* META_COMPOSITOR_PRIVATE_H */
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 5a70bb9..0950fa2 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -2,91 +2,24 @@
#include <config.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <gdk/gdk.h>
+#include <clutter/x11/clutter-x11.h>
-#include "../core/window-private.h"
#include "screen.h"
-#include "frame.h"
#include "errors.h"
#include "window.h"
#include "compositor-private.h"
#include "compositor-mutter.h"
-#include "mutter-plugin-manager.h"
#include "xprops.h"
#include "prefs.h"
-#include "shadow.h"
-#include "mutter-shaped-texture.h"
-#include <X11/Xatom.h>
-#include <X11/Xlibint.h>
+#include "mutter-window-private.h"
+#include "../core/window-private.h" /* to check window->hidden */
+#include "../core/display-private.h" /* for meta_display_lookup_x_window() */
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
-#include <X11/extensions/Xdamage.h>
-#include <X11/extensions/Xfixes.h>
-#include <X11/extensions/Xrender.h>
-
-#include <clutter/x11/clutter-x11.h>
-
-#define CHECK_LIST_INTEGRITY_START(list) \
- {int len2__; int len__ = g_list_length(list);
-
-#define CHECK_LIST_INTEGRITY_END(list) \
- len2__ = g_list_length(list); \
- if (len__ != len2__) \
- g_warning ("Integrity check of list failed at %s:%d\n", \
- __FILE__, __LINE__); }
/* #define DEBUG_TRACE g_print */
#define DEBUG_TRACE(X)
-/*
- * 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 ())
-
-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*) Xmalloc (sizeof (XWindowAttributes));
- *result = *attrs;
-
- return result;
-}
-
-static void
-meta_xattrs_free (XWindowAttributes *attrs)
-{
- g_return_if_fail (attrs != NULL);
-
- XFree (attrs);
-}
-
-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;
-}
-
static inline gboolean
composite_at_least_version (MetaDisplay *display, int maj, int min)
{
@@ -99,493 +32,6 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
return (major > maj || (major == maj && minor >= min));
}
-typedef struct _MetaCompScreen
-{
- MetaScreen *screen;
-
- ClutterActor *stage, *window_group, *overlay_group;
- ClutterActor *hidden_group;
- GList *windows;
- GHashTable *windows_by_xid;
- MetaWindow *focus_window;
- Window output;
- GSList *dock_windows;
-
- /* Before we create the output window */
- XserverRegion pending_input_region;
-
- gint switch_workspace_in_progress;
-
- MutterPluginManager *plugin_mgr;
-} MetaCompScreen;
-
-/*
- * MutterWindow implementation
- */
-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;
-
- /*
- * 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;
-
- guint shaped : 1;
- guint destroy_pending : 1;
- guint argb32 : 1;
- guint disposed : 1;
- guint is_minimized : 1;
- guint hide_after_effect : 1;
- guint redecorating : 1;
-
- /* Desktop switching flags */
- guint needs_map : 1;
- guint needs_unmap : 1;
- guint needs_repair : 1;
-
- 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_class_init (MutterWindowClass *klass);
-static void mutter_window_init (MutterWindow *self);
-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_query_window_type (MutterWindow *self);
-static void mutter_window_detach (MutterWindow *self);
-
-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 gboolean is_shaped (MetaDisplay *display, Window xwindow);
-static gboolean mutter_window_has_shadow (MutterWindow *self);
-static void update_shape (MetaCompositor *compositor,
- MutterWindow *cw);
-
-static void
-mutter_meta_window_decorated_notify (MetaWindow *mw,
- GParamSpec *arg1,
- gpointer data)
-{
- MutterWindow *mcw = MUTTER_WINDOW (data);
- MutterWindowPrivate *priv = mcw->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 (mcw);
-
- 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, mcw);
-
- 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 (mcw, "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 (mcw));
-}
-
-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;
- gulong value;
- MetaCompositor *compositor;
- Window xwin_child;
-
- compositor = meta_display_get_compositor (display);
- xwin_child = meta_window_get_xwindow (priv->window);
-
- mutter_window_query_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;
-
- if (meta_prop_get_cardinal (display, xwin_child,
- compositor->atom_net_wm_window_opacity,
- &value))
- {
- guint8 opacity;
-
- opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
-
- priv->opacity = opacity;
- clutter_actor_set_opacity (CLUTTER_ACTOR (self), opacity);
- }
-
- 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);
- }
-
-
- update_shape (compositor, self);
-}
-
-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);
-
- if (priv->damage != None)
- {
- meta_error_trap_push (display);
- XDamageDestroy (xdisplay, priv->damage);
- meta_error_trap_pop (display, FALSE);
-
- priv->damage = None;
- }
-
- /*
- * Check we are not in the dock list -- FIXME (do this in a cleaner way)
- */
- if (priv->type == META_COMP_WINDOW_DOCK)
- info->dock_windows = g_slist_remove (info->dock_windows, self);
-
- info->windows = g_list_remove (info->windows, (gconstpointer) self);
- g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
-
- g_free (priv->desc);
-
- G_OBJECT_CLASS (mutter_window_parent_class)->dispose (object);
-}
-
-static void
-mutter_window_finalize (GObject *object)
-{
- 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 *mw = MUTTER_WINDOW (object);
- MutterWindowPrivate *priv = mw->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 (mw))
- {
- 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 (mw), &w, &h);
-
- priv->shadow = mutter_create_shadow_frame (compositor);
-
- clutter_actor_set_size (priv->shadow, w, h);
-
- clutter_container_add_actor (CLUTTER_CONTAINER (mw), 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;
- }
-}
-
static MutterWindow*
find_window_for_screen (MetaScreen *screen, Window xwindow)
{
@@ -594,7 +40,8 @@ find_window_for_screen (MetaScreen *screen, Window xwindow)
if (info == NULL)
return NULL;
- return g_hash_table_lookup (info->windows_by_xid, (gpointer) xwindow);
+ return g_hash_table_lookup (info->windows_by_xid,
+ (gpointer) xwindow);
}
static MutterWindow *
@@ -638,229 +85,6 @@ find_window_for_child_window_in_display (MetaDisplay *display, Window xwindow)
return NULL;
}
-static void
-mutter_window_query_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 *mcw)
-{
- if (!mcw)
- return None;
-
- return mcw->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 *mcw)
-{
- return mcw->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 *mcw)
-{
- return mcw->priv->actor;
-}
-
-MetaCompWindowType
-mutter_window_get_window_type (MutterWindow *mcw)
-{
- if (!mcw)
- return 0;
-
- return mcw->priv->type;
-}
-
-gboolean
-mutter_window_is_override_redirect (MutterWindow *mcw)
-{
- if (mcw->priv->window->override_redirect)
- return TRUE;
-
- return FALSE;
-}
-
-const char *mutter_window_get_description (MutterWindow *mcw)
-{
- /*
- * 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 (mcw->priv->window)
- return meta_window_get_description (mcw->priv->window);
-
- if (G_UNLIKELY (mcw->priv->desc == NULL))
- {
- mcw->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
- (guint) mcw->priv->xwindow);
- }
-
- return mcw->priv->desc;
-}
-
-gint
-mutter_window_get_workspace (MutterWindow *mcw)
-{
- MutterWindowPrivate *priv;
- MetaWorkspace *workspace;
-
- if (!mcw)
- return -1;
-
- priv = mcw->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 *mcw)
-{
- if (!mcw)
- return FALSE;
-
- /* If override redirect: */
- if (!mcw->priv->window)
- return TRUE;
-
- return meta_window_showing_on_its_workspace (mcw->priv->window);
-}
-
-static void repair_win (MutterWindow *cw);
-static void map_win (MutterWindow *cw);
-static void unmap_win (MutterWindow *cw);
static void sync_actor_stacking (GList *windows);
static void
@@ -882,18 +106,7 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
while (l)
{
- MutterWindow *cw = l->data;
- MutterWindowPrivate *priv = cw->priv;
-
- if (priv->needs_map && !priv->needs_unmap)
- {
- map_win (cw);
- }
-
- if (priv->needs_unmap)
- {
- unmap_win (cw);
- }
+ mutter_window_finish_workspace_switch (l->data);
l = l->prev;
}
@@ -909,676 +122,50 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
}
-static gboolean
-effect_in_progress (MutterWindow *cw, gboolean include_destroy)
-{
- return (cw->priv->minimize_in_progress ||
- cw->priv->maximize_in_progress ||
- cw->priv->unmaximize_in_progress ||
- cw->priv->map_in_progress ||
- (include_destroy && cw->priv->destroy_in_progress));
-}
-
-void
-mutter_window_effect_completed (MutterWindow *cw, gulong event)
-{
- MutterWindowPrivate *priv = cw->priv;
- MetaScreen *screen = priv->screen;
- MetaCompScreen *info = meta_screen_get_compositor_data (screen);
- ClutterActor *actor = CLUTTER_ACTOR (cw);
- gboolean effect_done = FALSE;
-
- /* 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:
- {
- ClutterActor *a = CLUTTER_ACTOR (cw);
-
- priv->minimize_in_progress--;
- if (priv->minimize_in_progress < 0)
- {
- g_warning ("Error in minimize accounting.");
- priv->minimize_in_progress = 0;
- }
-
- if (!priv->minimize_in_progress)
- {
- priv->is_minimized = TRUE;
-
- /*
- * We must ensure that the minimized actor is pushed down the stack
- * (the XConfigureEvent has 'above' semantics, i.e., when a window
- * is lowered, we get a bunch of 'raise' notifications, but might
- * not get any notification for the window that has been lowered.
- */
- clutter_actor_lower_bottom (a);
-
- /* Make sure that after the effect finishes, the actor is
- * made visible for sake of live previews.
- */
- clutter_actor_show (a);
-
- effect_done = TRUE;
- }
- }
- 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;
- }
-
- if (!priv->map_in_progress && priv->window && !priv->no_more_x_calls)
- {
- MetaRectangle rect;
- meta_window_get_outer_rect (priv->window, &rect);
- priv->is_minimized = FALSE;
- clutter_actor_set_anchor_point (actor, 0, 0);
- clutter_actor_set_position (actor, rect.x, rect.y);
- clutter_actor_show_all (actor);
- effect_done = TRUE;
- }
- 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;
- }
-
- if (!priv->destroy_in_progress)
- {
- priv->needs_destroy = TRUE;
- effect_done = TRUE;
- }
- 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;
- }
-
- if (!priv->unmaximize_in_progress && priv->window && !priv->no_more_x_calls)
- {
- MetaRectangle rect;
- meta_window_get_outer_rect (priv->window, &rect);
- clutter_actor_set_position (actor, rect.x, rect.y);
- mutter_window_detach (cw);
- repair_win (cw);
- effect_done = TRUE;
- }
- 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;
- }
-
- if (!priv->maximize_in_progress && priv->window && !priv->no_more_x_calls)
- {
- MetaRectangle rect;
- meta_window_get_outer_rect (priv->window, &rect);
- clutter_actor_set_position (actor, rect.x, rect.y);
- mutter_window_detach (cw);
- repair_win (cw);
- effect_done = TRUE;
- }
- break;
- case MUTTER_PLUGIN_SWITCH_WORKSPACE:
- /* FIXME -- must redo stacking order */
- info->switch_workspace_in_progress--;
- if (info->switch_workspace_in_progress < 0)
- {
- g_warning ("Error in workspace_switch accounting!");
- info->switch_workspace_in_progress = 0;
- }
-
- if (!info->switch_workspace_in_progress)
- mutter_finish_workspace_switch (info);
- break;
- default:
- break;
- }
-
- switch (event)
- {
- case MUTTER_PLUGIN_MINIMIZE:
- case MUTTER_PLUGIN_MAP:
- case MUTTER_PLUGIN_DESTROY:
- case MUTTER_PLUGIN_UNMAXIMIZE:
- case MUTTER_PLUGIN_MAXIMIZE:
-
- if (effect_done &&
- priv->hide_after_effect &&
- effect_in_progress (cw, TRUE) == FALSE)
- {
- if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group)
- {
- clutter_actor_reparent (CLUTTER_ACTOR (cw),
- info->hidden_group);
- }
- priv->hide_after_effect = FALSE;
- }
-
- if (priv->needs_destroy && effect_in_progress (cw, TRUE) == FALSE)
- {
- clutter_actor_destroy (CLUTTER_ACTOR (cw));
- return;
- }
-
- default:
- break;
- }
-}
-
-
void
-meta_compositor_destroy (MetaCompositor *compositor)
-{
-}
-
-static void
-mutter_window_detach (MutterWindow *self)
+mutter_switch_workspace_completed (MetaScreen *screen)
{
- 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;
-}
-
-static void
-destroy_win (MutterWindow *cw)
-{
- MetaWindow *window;
- MetaCompScreen *info;
- MutterWindowPrivate *priv;
-
- priv = cw->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) cw);
- 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 (cw));
- return;
- }
-
- /*
- * If a plugin manager is present, try to run an effect; if no effect of this
- * type is present, destroy the actor.
- */
- priv->destroy_in_progress++;
-
- /*
- * 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;
+ MetaCompScreen *info = meta_screen_get_compositor_data (screen);
- if (!info->plugin_mgr ||
- !mutter_plugin_manager_event_simple (info->plugin_mgr,
- cw,
- MUTTER_PLUGIN_DESTROY))
+ /* FIXME -- must redo stacking order */
+ info->switch_workspace_in_progress--;
+ if (info->switch_workspace_in_progress < 0)
{
- priv->destroy_in_progress--;
-
- if (effect_in_progress (cw, FALSE))
- {
- priv->needs_destroy = TRUE;
- }
- else
- clutter_actor_destroy (CLUTTER_ACTOR (cw));
+ g_warning ("Error in workspace_switch accounting!");
+ info->switch_workspace_in_progress = 0;
}
-}
-
-static void
-sync_actor_position (MutterWindow *cw)
-{
- MutterWindowPrivate *priv = cw->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)
- mutter_window_detach (cw);
-
- /* 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;
-
- if (effect_in_progress (cw, FALSE))
- return;
-
- clutter_actor_set_position (CLUTTER_ACTOR (cw),
- window_rect.x, window_rect.y);
-}
-
-static void
-map_win (MutterWindow *cw)
-{
- MutterWindowPrivate *priv;
- MetaCompScreen *info;
-
- if (!cw)
- return;
-
- priv = cw->priv;
- info = meta_screen_get_compositor_data (priv->screen);
-
- if (priv->attrs.map_state == IsViewable)
- return;
-
- priv->attrs.map_state = IsViewable;
-
- /*
- * Now repair the window; this ensures that the actor is correctly sized
- * before we run any effects on it.
- */
- priv->needs_map = FALSE;
- mutter_window_detach (cw);
- repair_win (cw);
-
- /*
- * Make sure the position is set correctly (we might have got moved while
- * unmapped.
- */
if (!info->switch_workspace_in_progress)
- {
- MetaRectangle rect;
- meta_window_get_outer_rect (priv->window, &rect);
- clutter_actor_set_anchor_point (CLUTTER_ACTOR (cw), 0, 0);
- clutter_actor_set_position (CLUTTER_ACTOR (cw), rect.x, rect.y);
- }
-
- priv->map_in_progress++;
-
- /*
- * If a plugin manager is present, try to run an effect; if no effect of this
- * type is present, destroy the actor.
- */
- if (priv->redecorating ||
- info->switch_workspace_in_progress || !info->plugin_mgr ||
- !mutter_plugin_manager_event_simple (info->plugin_mgr,
- cw,
- MUTTER_PLUGIN_MAP))
- {
- clutter_actor_show_all (CLUTTER_ACTOR (cw));
- priv->map_in_progress--;
- priv->is_minimized = FALSE;
- priv->redecorating = FALSE;
- }
+ mutter_finish_workspace_switch (info);
}
-static void
-unmap_win (MutterWindow *cw)
+void
+meta_compositor_destroy (MetaCompositor *compositor)
{
- MutterWindowPrivate *priv;
- MetaCompScreen *info;
-
- if (!cw)
- return;
-
- priv = cw->priv;
- info = meta_screen_get_compositor_data (priv->screen);
-
- /*
- * If the needs_unmap flag is set, we carry on even if the winow is
- * already marked as unmapped; this is necessary so windows temporarily
- * shown during an effect (like desktop switch) are properly hidden again.
- */
- if (priv->attrs.map_state == IsUnmapped && !priv->needs_unmap)
- return;
-
- if (priv->window && priv->window == info->focus_window)
- info->focus_window = NULL;
-
- if (info->switch_workspace_in_progress)
- {
- /*
- * Cannot unmap windows while switching desktops effect is in progress.
- */
- priv->needs_unmap = TRUE;
- return;
- }
-
- priv->attrs.map_state = IsUnmapped;
- priv->needs_unmap = FALSE;
- priv->needs_map = FALSE;
-
- if (!priv->minimize_in_progress &&
- (!meta_prefs_get_live_hidden_windows () ||
- 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))
- {
- clutter_actor_hide (CLUTTER_ACTOR (cw));
- }
}
static void
add_win (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 *cw;
- MutterWindowPrivate *priv;
- MetaFrame *frame;
- Window top_window;
- XWindowAttributes attrs;
g_return_if_fail (info != NULL);
- 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 cw->priv->attrs, and
- * simply query metacity core for the data. */
- if (!XGetWindowAttributes (display->xdisplay, top_window, &attrs))
- return;
-
- cw = g_object_new (MUTTER_TYPE_COMP_WINDOW,
- "meta-window", window,
- "x-window", top_window,
- "meta-screen", screen,
- "x-window-attributes", &attrs,
- NULL);
-
- priv = cw->priv;
-
- clutter_actor_set_position (CLUTTER_ACTOR (cw),
- priv->attrs.x, priv->attrs.y);
-
- clutter_container_add_actor (CLUTTER_CONTAINER (info->window_group),
- CLUTTER_ACTOR (cw));
- clutter_actor_hide (CLUTTER_ACTOR (cw));
-
- if (priv->type == META_COMP_WINDOW_DOCK)
- {
- meta_verbose ("Appending 0x%x to dock windows\n", (guint)top_window);
- info->dock_windows = g_slist_append (info->dock_windows, cw);
- }
-
- meta_verbose ("added 0x%x (%p) type:", (guint)top_window, cw);
-
- /* Hang our compositor window state off the MetaWindow for fast retrieval */
- meta_window_set_compositor_private (window, G_OBJECT (cw));
-
- /*
- * Add this to the list at the top of the stack before it is mapped so that
- * map_win can find it again
- */
- info->windows = g_list_append (info->windows, cw);
- g_hash_table_insert (info->windows_by_xid, (gpointer) top_window, cw);
-
- if (priv->attrs.map_state == IsViewable)
- {
- /* Need to reset the map_state for map_win() to work */
- priv->attrs.map_state = IsUnmapped;
- map_win (cw);
- }
+ mutter_window_new (window);
sync_actor_stacking (info->windows);
}
static void
-repair_win (MutterWindow *cw)
-{
- MutterWindowPrivate *priv = cw->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;
-
- if (xwindow == meta_screen_get_xroot (screen) ||
- xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
- return;
-
- compositor = meta_display_get_compositor (display);
-
- 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", cw);
- 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);
-
- clutter_actor_set_size (priv->actor, pxm_width, pxm_height);
-
- if (priv->shadow)
- clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
-
- 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;
-}
-
-static void
process_damage (MetaCompositor *compositor,
XDamageNotifyEvent *event)
{
- XEvent next;
- Display *dpy = event->display;
- Drawable drawable = event->drawable;
- MutterWindowPrivate *priv;
- MutterWindow *cw = find_window_in_display (compositor->display, drawable);
-
- if (!cw)
+ MutterWindow *cw = find_window_in_display (compositor->display, event->drawable);
+ if (cw == NULL)
return;
- priv = cw->priv;
-
- if (priv->destroy_pending ||
- priv->maximize_in_progress ||
- priv->unmaximize_in_progress)
- {
- priv->needs_repair = TRUE;
- return;
- }
-
- /*
- * Check if the event queue does not already contain DetstroyNotify for this
- * window -- if it does, we need to stop updating the pixmap (to avoid damage
- * notifications that come from the window teardown), and process the destroy
- * immediately.
- */
- if (XCheckTypedWindowEvent (dpy, drawable, DestroyNotify, &next))
- {
- priv->destroy_pending = TRUE;
- destroy_win (cw);
- return;
- }
-
- repair_win (cw);
-}
-
-static void
-update_shape (MetaCompositor *compositor,
- MutterWindow *cw)
-{
- MutterWindowPrivate *priv = cw->priv;
-
- mutter_shaped_texture_clear_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor));
-
-#ifdef HAVE_SHAPE
- if (priv->shaped)
- {
- Display *xdisplay = meta_display_get_xdisplay (compositor->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);
-
- XFree (rects);
- }
- }
-#endif
+ mutter_window_process_damage (cw, event);
}
#ifdef HAVE_SHAPE
@@ -1588,17 +175,12 @@ process_shape (MetaCompositor *compositor,
{
MutterWindow *cw = find_window_in_display (compositor->display,
event->window);
- MutterWindowPrivate *priv;
-
if (cw == NULL)
return;
- priv = cw->priv;
-
if (event->kind == ShapeBounding)
{
- priv->shaped = event->shaped;
- update_shape (compositor, cw);
+ mutter_window_update_shape (cw, event->shaped);
}
}
#endif
@@ -1613,7 +195,6 @@ process_property_notify (MetaCompositor *compositor,
if (event->atom == compositor->atom_net_wm_window_opacity)
{
MutterWindow *cw = find_window_in_display (display, event->window);
- gulong value;
if (!cw)
{
@@ -1630,19 +211,7 @@ process_property_notify (MetaCompositor *compositor,
return;
}
- if (meta_prop_get_cardinal (display, event->window,
- compositor->atom_net_wm_window_opacity,
- &value))
- {
- guint8 opacity;
-
- opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
-
- cw->priv->opacity = opacity;
- clutter_actor_set_opacity (CLUTTER_ACTOR (cw), opacity);
- }
-
- return;
+ mutter_window_update_opacity (cw);
}
else if (event->atom == meta_display_get_atom (display,
META_ATOM__NET_WM_WINDOW_TYPE))
@@ -1655,7 +224,7 @@ process_property_notify (MetaCompositor *compositor,
return;
}
- mutter_window_query_window_type (cw);
+ mutter_window_update_window_type (cw);
DEBUG_TRACE ("process_property_notify: net_wm_type\n");
return;
}
@@ -1951,7 +520,7 @@ meta_compositor_remove_window (MetaCompositor *compositor,
if (!cw)
return;
- destroy_win (cw);
+ mutter_window_destroy (cw);
}
void
@@ -2056,7 +625,7 @@ meta_compositor_map_window (MetaCompositor *compositor,
if (!cw)
return;
- map_win (cw);
+ mutter_window_map (cw);
}
void
@@ -2068,7 +637,7 @@ meta_compositor_unmap_window (MetaCompositor *compositor,
if (!cw)
return;
- unmap_win (cw);
+ mutter_window_unmap (cw);
}
void
@@ -2088,20 +657,7 @@ meta_compositor_minimize_window (MetaCompositor *compositor,
if (!cw)
return;
- /*
- * If there is a plugin manager, try to run an effect; if no effect is
- * executed, hide the actor.
- */
- cw->priv->minimize_in_progress++;
-
- if (!info->plugin_mgr ||
- !mutter_plugin_manager_event_simple (info->plugin_mgr,
- cw,
- MUTTER_PLUGIN_MINIMIZE))
- {
- cw->priv->is_minimized = TRUE;
- cw->priv->minimize_in_progress--;
- }
+ mutter_window_minimize (cw);
}
void
@@ -2140,7 +696,7 @@ meta_compositor_unminimize_window (MetaCompositor *compositor,
if (!cw)
return;
- map_win (cw);
+ mutter_window_map (cw);
#endif
}
@@ -2151,26 +707,11 @@ meta_compositor_maximize_window (MetaCompositor *compositor,
MetaRectangle *window_rect)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
- MetaScreen *screen = meta_window_get_screen (window);
- MetaCompScreen *info = meta_screen_get_compositor_data (screen);
-
DEBUG_TRACE ("clutter_cmp_maximize_window\n");
- g_return_if_fail (info);
-
if (!cw)
return;
- cw->priv->maximize_in_progress++;
-
- if (!info->plugin_mgr ||
- !mutter_plugin_manager_event_maximize (info->plugin_mgr,
- cw,
- MUTTER_PLUGIN_MAXIMIZE,
- window_rect->x, window_rect->y,
- window_rect->width, window_rect->height))
- {
- cw->priv->maximize_in_progress--;
- }
+ mutter_window_maximize (cw, window_rect);
}
void
@@ -2179,26 +720,11 @@ meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaRectangle *window_rect)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
- MetaScreen *screen = meta_window_get_screen (window);
- MetaCompScreen *info = meta_screen_get_compositor_data (screen);
-
- g_return_if_fail (info);
-
DEBUG_TRACE ("clutter_cmp_unmaximize_window\n");
if (!cw)
return;
- cw->priv->unmaximize_in_progress++;
-
- if (!info->plugin_mgr ||
- !mutter_plugin_manager_event_maximize (info->plugin_mgr,
- cw,
- MUTTER_PLUGIN_UNMAXIMIZE,
- window_rect->x, window_rect->y,
- window_rect->width, window_rect->height))
- {
- cw->priv->unmaximize_in_progress--;
- }
+ mutter_window_unmaximize (cw, window_rect);
}
void
@@ -2253,7 +779,7 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
for (l = info->windows; l != NULL; l = l->next)
{
MutterWindow *cw = l->data;
- MetaWindow *mw = cw->priv->window;
+ MetaWindow *mw = mutter_window_get_meta_window (cw);
gboolean sticky;
gint workspace = -1;
@@ -2263,22 +789,14 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
{
MetaWorkspace *w;
- w = meta_window_get_workspace (cw->priv->window);
+ w = meta_window_get_workspace (mw);
workspace = meta_workspace_index (w);
/*
* If the window is not on the target workspace, mark it for
* unmap.
*/
- if (to_indx != workspace)
- {
- cw->priv->needs_unmap = TRUE;
- }
- else
- {
- cw->priv->needs_map = TRUE;
- cw->priv->needs_unmap = FALSE;
- }
+ mutter_window_queue_map_change (cw, to_indx == workspace);
}
}
}
@@ -2352,7 +870,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
old_window = mutter_window_get_meta_window (old_actor);
if (old_window->hidden &&
- !effect_in_progress (old_actor, TRUE))
+ !mutter_window_effect_in_progress (old_actor, TRUE))
old_stack = g_list_delete_link (old_stack, old_stack);
else
break;
@@ -2414,35 +932,13 @@ meta_compositor_set_window_hidden (MetaCompositor *compositor,
gboolean hidden)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
- MutterWindowPrivate *priv = cw->priv;
- MetaCompScreen *info = meta_screen_get_compositor_data (screen);
DEBUG_TRACE ("clutter_cmp_set_window_hidden\n");
+
if (!cw)
return;
- if (hidden)
- {
- if (effect_in_progress (cw, TRUE))
- {
- priv->hide_after_effect = TRUE;
- }
- else
- {
- if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group)
- {
- clutter_actor_reparent (CLUTTER_ACTOR (cw),
- info->hidden_group);
- }
- }
- }
- else
- {
- priv->hide_after_effect = FALSE;
- if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->window_group)
- clutter_actor_reparent (CLUTTER_ACTOR (cw),
- info->window_group);
- }
+ mutter_window_set_hidden (cw, hidden);
}
void
@@ -2459,7 +955,7 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
if (!cw)
return;
- sync_actor_position (cw);
+ mutter_window_sync_actor_position (cw);
}
void
diff --git a/src/compositor/mutter-plugin.c b/src/compositor/mutter-plugin.c
index 7714344..18763da 100644
--- a/src/compositor/mutter-plugin.c
+++ b/src/compositor/mutter-plugin.c
@@ -31,6 +31,9 @@
#include <X11/extensions/shape.h>
#include <clutter/x11/clutter-x11.h>
+#include "compositor-private.h"
+#include "mutter-window-private.h"
+
G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
#define MUTTER_PLUGIN_GET_PRIVATE(obj) \
@@ -389,7 +392,17 @@ mutter_plugin_effect_completed (MutterPlugin *plugin,
name ? name : "unknown");
}
- mutter_window_effect_completed (actor, event);
+ if (event == MUTTER_PLUGIN_SWITCH_WORKSPACE)
+ {
+ /* The window is just used to identify the screen */
+ MetaWindow *window = mutter_window_get_meta_window (actor);
+ MetaScreen *screen = meta_window_get_screen (window);
+ mutter_switch_workspace_completed (screen);
+ }
+ else
+ {
+ mutter_window_effect_completed (actor, event);
+ }
}
void
diff --git a/src/compositor/mutter-window-private.h b/src/compositor/mutter-window-private.h
new file mode 100644
index 0000000..68be514
--- /dev/null
+++ b/src/compositor/mutter-window-private.h
@@ -0,0 +1,39 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+#ifndef MUTTER_WINDOW_PRIVATE_H
+#define MUTTER_WINDOW_PRIVATE_H
+
+#include <X11/extensions/Xdamage.h>
+#include "compositor-mutter.h"
+
+MutterWindow *mutter_window_new (MetaWindow *window);
+
+void mutter_window_map (MutterWindow *cw);
+void mutter_window_unmap (MutterWindow *cw);
+void mutter_window_minimize (MutterWindow *cw);
+void mutter_window_destroy (MutterWindow *cw);
+
+void mutter_window_maximize (MutterWindow *cw,
+ MetaRectangle *window_rect);
+void mutter_window_unmaximize (MutterWindow *cw,
+ MetaRectangle *window_rect);
+
+void mutter_window_process_damage (MutterWindow *cw,
+ XDamageNotifyEvent *event);
+gboolean mutter_window_effect_in_progress (MutterWindow *cw,
+ gboolean include_destroy);
+void mutter_window_sync_actor_position (MutterWindow *cw);
+void mutter_window_finish_workspace_switch (MutterWindow *cw);
+void mutter_window_update_window_type (MutterWindow *cw);
+void mutter_window_update_shape (MutterWindow *cw,
+ gboolean shaped);
+void mutter_window_update_opacity (MutterWindow *cw);
+void mutter_window_set_hidden (MutterWindow *cw,
+ gboolean hidden);
+void mutter_window_queue_map_change (MutterWindow *cw,
+ gboolean should_be_mapped);
+
+void mutter_window_effect_completed (MutterWindow *actor,
+ gulong event);
+
+#endif /* MUTTER_WINDOW_PRIVATE_H */
diff --git a/src/compositor/mutter-window.c b/src/compositor/mutter-window.c
new file mode 100644
index 0000000..3a95067
--- /dev/null
+++ b/src/compositor/mutter-window.c
@@ -0,0 +1,1528 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+#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"
+
+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;
+
+ /*
+ * 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;
+
+ guint shaped : 1;
+ guint destroy_pending : 1;
+ guint argb32 : 1;
+ guint disposed : 1;
+ guint is_minimized : 1;
+ guint hide_after_effect : 1;
+ guint redecorating : 1;
+
+ /* Desktop switching flags */
+ guint needs_map : 1;
+ guint needs_unmap : 1;
+ guint needs_repair : 1;
+
+ 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);
+
+
+static void repair_win (MutterWindow *self);
+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);
+
+ if (priv->damage != None)
+ {
+ meta_error_trap_push (display);
+ XDamageDestroy (xdisplay, priv->damage);
+ meta_error_trap_pop (display, FALSE);
+
+ priv->damage = None;
+ }
+
+ /*
+ * Check we are not in the dock list -- FIXME (do this in a cleaner way)
+ */
+ if (priv->type == META_COMP_WINDOW_DOCK)
+ info->dock_windows = g_slist_remove (info->dock_windows, self);
+
+ info->windows = g_list_remove (info->windows, (gconstpointer) self);
+ g_hash_table_remove (info->windows_by_xid, (gpointer) priv->xwindow);
+
+ g_free (priv->desc);
+
+ G_OBJECT_CLASS (mutter_window_parent_class)->dispose (object);
+}
+
+static void
+mutter_window_finalize (GObject *object)
+{
+ 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
+mutter_window_effect_in_progress (MutterWindow *self,
+ gboolean include_destroy)
+{
+ return (self->priv->minimize_in_progress ||
+ self->priv->maximize_in_progress ||
+ self->priv->unmaximize_in_progress ||
+ self->priv->map_in_progress ||
+ (include_destroy && self->priv->destroy_in_progress));
+}
+
+void
+mutter_window_effect_completed (MutterWindow *self,
+ gulong event)
+{
+ MutterWindowPrivate *priv = self->priv;
+ MetaScreen *screen = priv->screen;
+ MetaCompScreen *info = meta_screen_get_compositor_data (screen);
+ ClutterActor *actor = CLUTTER_ACTOR (self);
+ gboolean effect_done = FALSE;
+
+ /* 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:
+ {
+ ClutterActor *a = CLUTTER_ACTOR (self);
+
+ priv->minimize_in_progress--;
+ if (priv->minimize_in_progress < 0)
+ {
+ g_warning ("Error in minimize accounting.");
+ priv->minimize_in_progress = 0;
+ }
+
+ if (!priv->minimize_in_progress)
+ {
+ priv->is_minimized = TRUE;
+
+ /*
+ * We must ensure that the minimized actor is pushed down the stack
+ * (the XConfigureEvent has 'above' semantics, i.e., when a window
+ * is lowered, we get a bunch of 'raise' notifications, but might
+ * not get any notification for the window that has been lowered.
+ */
+ clutter_actor_lower_bottom (a);
+
+ /* Make sure that after the effect finishes, the actor is
+ * made visible for sake of live previews.
+ */
+ clutter_actor_show (a);
+
+ effect_done = TRUE;
+ }
+ }
+ 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;
+ }
+
+ if (!priv->map_in_progress && priv->window && !priv->no_more_x_calls)
+ {
+ MetaRectangle rect;
+ meta_window_get_outer_rect (priv->window, &rect);
+ priv->is_minimized = FALSE;
+ clutter_actor_set_anchor_point (actor, 0, 0);
+ clutter_actor_set_position (actor, rect.x, rect.y);
+ clutter_actor_show_all (actor);
+ effect_done = TRUE;
+ }
+ 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;
+ }
+
+ if (!priv->destroy_in_progress)
+ {
+ priv->needs_destroy = TRUE;
+ effect_done = TRUE;
+ }
+ 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;
+ }
+
+ if (!priv->unmaximize_in_progress && priv->window && !priv->no_more_x_calls)
+ {
+ MetaRectangle rect;
+ meta_window_get_outer_rect (priv->window, &rect);
+ clutter_actor_set_position (actor, rect.x, rect.y);
+ mutter_window_detach (self);
+ repair_win (self);
+ effect_done = TRUE;
+ }
+ 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;
+ }
+
+ if (!priv->maximize_in_progress && priv->window && !priv->no_more_x_calls)
+ {
+ MetaRectangle rect;
+ meta_window_get_outer_rect (priv->window, &rect);
+ clutter_actor_set_position (actor, rect.x, rect.y);
+ mutter_window_detach (self);
+ repair_win (self);
+ effect_done = TRUE;
+ }
+ break;
+ case MUTTER_PLUGIN_SWITCH_WORKSPACE:
+ g_assert_not_reached ();
+ break;
+ default:
+ break;
+ }
+
+ switch (event)
+ {
+ case MUTTER_PLUGIN_MINIMIZE:
+ case MUTTER_PLUGIN_MAP:
+ case MUTTER_PLUGIN_DESTROY:
+ case MUTTER_PLUGIN_UNMAXIMIZE:
+ case MUTTER_PLUGIN_MAXIMIZE:
+
+ if (effect_done &&
+ priv->hide_after_effect &&
+ mutter_window_effect_in_progress (self, TRUE) == FALSE)
+ {
+ if (clutter_actor_get_parent (CLUTTER_ACTOR (self)) != info->hidden_group)
+ {
+ clutter_actor_reparent (CLUTTER_ACTOR (self),
+ info->hidden_group);
+ }
+ priv->hide_after_effect = FALSE;
+ }
+
+ if (priv->needs_destroy && mutter_window_effect_in_progress (self, TRUE) == FALSE)
+ {
+ clutter_actor_destroy (CLUTTER_ACTOR (self));
+ return;
+ }
+
+ default:
+ break;
+ }
+}
+
+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;
+}
+
+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;
+ }
+
+ /*
+ * If a plugin manager is present, try to run an effect; if no effect of this
+ * type is present, destroy the actor.
+ */
+ priv->destroy_in_progress++;
+
+ /*
+ * 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;
+
+ if (!info->plugin_mgr ||
+ !mutter_plugin_manager_event_simple (info->plugin_mgr,
+ self,
+ MUTTER_PLUGIN_DESTROY))
+ {
+ priv->destroy_in_progress--;
+
+ if (mutter_window_effect_in_progress (self, FALSE))
+ {
+ priv->needs_destroy = TRUE;
+ }
+ else
+ clutter_actor_destroy (CLUTTER_ACTOR (self));
+ }
+}
+
+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)
+ mutter_window_detach (self);
+
+ /* 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;
+
+ if (mutter_window_effect_in_progress (self, FALSE))
+ return;
+
+ clutter_actor_set_position (CLUTTER_ACTOR (self),
+ window_rect.x, window_rect.y);
+}
+
+void
+mutter_window_map (MutterWindow *self)
+{
+ MutterWindowPrivate *priv;
+ MetaCompScreen *info;
+
+ if (!self)
+ return;
+
+ priv = self->priv;
+ info = meta_screen_get_compositor_data (priv->screen);
+
+ if (priv->attrs.map_state == IsViewable)
+ return;
+
+ priv->attrs.map_state = IsViewable;
+
+ /*
+ * Now repair the window; this ensures that the actor is correctly sized
+ * before we run any effects on it.
+ */
+ priv->needs_map = FALSE;
+ mutter_window_detach (self);
+ repair_win (self);
+
+ /*
+ * Make sure the position is set correctly (we might have got moved while
+ * unmapped.
+ */
+ if (!info->switch_workspace_in_progress)
+ {
+ MetaRectangle rect;
+ meta_window_get_outer_rect (priv->window, &rect);
+ clutter_actor_set_anchor_point (CLUTTER_ACTOR (self), 0, 0);
+ clutter_actor_set_position (CLUTTER_ACTOR (self), rect.x, rect.y);
+ }
+
+ priv->map_in_progress++;
+
+ /*
+ * If a plugin manager is present, try to run an effect; if no effect of this
+ * type is present, destroy the actor.
+ */
+ if (priv->redecorating ||
+ info->switch_workspace_in_progress || !info->plugin_mgr ||
+ !mutter_plugin_manager_event_simple (info->plugin_mgr,
+ self,
+ MUTTER_PLUGIN_MAP))
+ {
+ clutter_actor_show_all (CLUTTER_ACTOR (self));
+ priv->map_in_progress--;
+ priv->is_minimized = FALSE;
+ priv->redecorating = FALSE;
+ }
+}
+
+void
+mutter_window_unmap (MutterWindow *self)
+{
+ MutterWindowPrivate *priv;
+ MetaCompScreen *info;
+
+ priv = self->priv;
+ info = meta_screen_get_compositor_data (priv->screen);
+
+ /*
+ * If the needs_unmap flag is set, we carry on even if the winow is
+ * already marked as unmapped; this is necessary so windows temporarily
+ * shown during an effect (like desktop switch) are properly hidden again.
+ */
+ if (priv->attrs.map_state == IsUnmapped && !priv->needs_unmap)
+ return;
+
+ if (priv->window && priv->window == info->focus_window)
+ info->focus_window = NULL;
+
+ if (info->switch_workspace_in_progress)
+ {
+ /*
+ * Cannot unmap windows while switching desktops effect is in progress.
+ */
+ priv->needs_unmap = TRUE;
+ return;
+ }
+
+ priv->attrs.map_state = IsUnmapped;
+ priv->needs_unmap = FALSE;
+ priv->needs_map = FALSE;
+
+ if (!priv->minimize_in_progress &&
+ (!meta_prefs_get_live_hidden_windows () ||
+ 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))
+ {
+ clutter_actor_hide (CLUTTER_ACTOR (self));
+ }
+}
+
+void
+mutter_window_minimize (MutterWindow *self)
+{
+ MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
+
+ /*
+ * If there is a plugin manager, try to run an effect; if no effect is
+ * executed, hide the actor.
+ */
+ self->priv->minimize_in_progress++;
+
+ if (!info->plugin_mgr ||
+ !mutter_plugin_manager_event_simple (info->plugin_mgr,
+ self,
+ MUTTER_PLUGIN_MINIMIZE))
+ {
+ self->priv->is_minimized = TRUE;
+ self->priv->minimize_in_progress--;
+ }
+}
+
+void
+mutter_window_maximize (MutterWindow *self,
+ MetaRectangle *window_rect)
+{
+ MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
+
+ self->priv->maximize_in_progress++;
+
+ if (!info->plugin_mgr ||
+ !mutter_plugin_manager_event_maximize (info->plugin_mgr,
+ self,
+ MUTTER_PLUGIN_MAXIMIZE,
+ window_rect->x, window_rect->y,
+ window_rect->width, window_rect->height))
+
+ {
+ self->priv->maximize_in_progress--;
+ }
+}
+
+void
+mutter_window_unmaximize (MutterWindow *self,
+ MetaRectangle *window_rect)
+{
+ MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
+
+ self->priv->unmaximize_in_progress++;
+
+ if (!info->plugin_mgr ||
+ !mutter_plugin_manager_event_maximize (info->plugin_mgr,
+ self,
+ MUTTER_PLUGIN_UNMAXIMIZE,
+ window_rect->x, window_rect->y,
+ window_rect->width, window_rect->height))
+ {
+ 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;
+
+ clutter_actor_set_position (CLUTTER_ACTOR (self),
+ priv->attrs.x, priv->attrs.y);
+
+ /* 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));
+
+ if (priv->type == META_COMP_WINDOW_DOCK)
+ {
+ meta_verbose ("Appending %s to dock windows\n", meta_window_get_description (window));
+ info->dock_windows = g_slist_append (info->dock_windows, self);
+ }
+
+ /*
+ * Add this to the list at the top of the stack before it is mapped so that
+ * map_win can find it again
+ */
+ info->windows = g_list_append (info->windows, self);
+ g_hash_table_insert (info->windows_by_xid, (gpointer) top_window, self);
+
+ if (priv->attrs.map_state == IsViewable)
+ {
+ /* Need to reset the map_state for map_win() to work */
+ priv->attrs.map_state = IsUnmapped;
+ mutter_window_map (self);
+ }
+
+ return self;
+}
+
+static void
+repair_win (MutterWindow *self)
+{
+ 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;
+
+ if (xwindow == meta_screen_get_xroot (screen) ||
+ xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
+ return;
+
+ compositor = meta_display_get_compositor (display);
+
+ 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);
+ 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);
+
+ clutter_actor_set_size (priv->actor, pxm_width, pxm_height);
+
+ if (priv->shadow)
+ clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
+
+ 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)
+{
+ MutterWindowPrivate *priv = self->priv;
+ Display *dpy = event->display;
+ Drawable drawable = event->drawable;
+ XEvent next;
+
+ if (priv->destroy_pending ||
+ priv->maximize_in_progress ||
+ priv->unmaximize_in_progress)
+ {
+ priv->needs_repair = TRUE;
+ return;
+ }
+
+ /*
+ * Check if the event queue does not already contain DetstroyNotify for this
+ * window -- if it does, we need to stop updating the pixmap (to avoid damage
+ * notifications that come from the window teardown), and process the destroy
+ * immediately.
+ */
+ if (XCheckTypedWindowEvent (dpy, drawable, DestroyNotify, &next))
+ {
+ priv->destroy_pending = TRUE;
+ mutter_window_destroy (self);
+ return;
+ }
+
+ repair_win (self);
+}
+
+void
+mutter_window_finish_workspace_switch (MutterWindow *self)
+{
+ MutterWindowPrivate *priv = self->priv;
+
+ if (priv->needs_map && !priv->needs_unmap)
+ {
+ mutter_window_map (self);
+ }
+
+ if (priv->needs_unmap)
+ {
+ mutter_window_unmap (self);
+ }
+}
+
+void
+mutter_window_update_shape (MutterWindow *self,
+ gboolean shaped)
+{
+ MutterWindowPrivate *priv = self->priv;
+
+ priv->shaped = shaped;
+
+ mutter_shaped_texture_clear_rectangles (MUTTER_SHAPED_TEXTURE (priv->actor));
+
+#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);
+
+ XFree (rects);
+ }
+ }
+#endif
+}
+
+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);
+}
+
+void
+mutter_window_set_hidden (MutterWindow *self,
+ gboolean hidden)
+{
+ MutterWindowPrivate *priv = self->priv;
+ MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
+
+ if (hidden)
+ {
+ if (mutter_window_effect_in_progress (self, TRUE))
+ {
+ priv->hide_after_effect = TRUE;
+ }
+ else
+ {
+ if (clutter_actor_get_parent (CLUTTER_ACTOR (self)) != info->hidden_group)
+ {
+ clutter_actor_reparent (CLUTTER_ACTOR (self),
+ info->hidden_group);
+ }
+ }
+ }
+ else
+ {
+ priv->hide_after_effect = FALSE;
+ if (clutter_actor_get_parent (CLUTTER_ACTOR (self)) != info->window_group)
+ clutter_actor_reparent (CLUTTER_ACTOR (self),
+ info->window_group);
+ }
+}
+
+void
+mutter_window_queue_map_change (MutterWindow *self,
+ gboolean should_be_mapped)
+{
+ if (should_be_mapped)
+ {
+ self->priv->needs_map = TRUE;
+ self->priv->needs_unmap = FALSE;
+ }
+ else
+ {
+ self->priv->needs_unmap = TRUE;
+ }
+}
diff --git a/src/include/compositor-mutter.h b/src/include/compositor-mutter.h
index 7ab3511..ba3ab0c 100644
--- a/src/include/compositor-mutter.h
+++ b/src/include/compositor-mutter.h
@@ -26,63 +26,17 @@
#define MUTTER_H_
#include <clutter/clutter.h>
-#include <X11/extensions/Xfixes.h>
#include <X11/Xlib.h>
#include "types.h"
#include "compositor.h"
+#include "mutter-window.h"
-/*
- * MutterWindow object (ClutterGroup sub-class)
- */
-#define MUTTER_TYPE_COMP_WINDOW (mutter_window_get_type ())
-#define MUTTER_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindow))
-#define MUTTER_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
-#define MUTTER_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_TYPE_COMP_WINDOW))
-#define MUTTER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_COMP_WINDOW))
-#define MUTTER_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
-
-typedef struct _MutterWindow MutterWindow;
-typedef struct _MutterWindowClass MutterWindowClass;
-typedef struct _MutterWindowPrivate MutterWindowPrivate;
-
-struct _MutterWindowClass
-{
- ClutterGroupClass parent_class;
-};
-
-struct _MutterWindow
-{
- ClutterGroup parent;
-
- MutterWindowPrivate *priv;
-};
-
-GType mutter_window_get_type (void);
-
-Window mutter_window_get_x_window (MutterWindow *mcw);
-MetaCompWindowType mutter_window_get_window_type (MutterWindow *mcw);
-gint mutter_window_get_workspace (MutterWindow *mcw);
-gboolean mutter_window_is_hidden (MutterWindow *mcw);
-MetaWindow * mutter_window_get_meta_window (MutterWindow *mcw);
-ClutterActor * mutter_window_get_texture (MutterWindow *mcw);
-gboolean mutter_window_is_override_redirect (MutterWindow *mcw);
-const char * mutter_window_get_description (MutterWindow *mcw);
-gboolean mutter_window_showing_on_its_workspace (MutterWindow *mcw);
-
-/* Compositor API */
-MetaCompositor *mutter_new (MetaDisplay *display);
-
-void mutter_window_effect_completed (MutterWindow *actor, gulong event);
-
+/* Public compositor API */
ClutterActor * mutter_get_stage_for_screen (MetaScreen *screen);
ClutterActor * mutter_get_overlay_group_for_screen (MetaScreen *screen);
Window mutter_get_overlay_window (MetaScreen *screen);
GList * mutter_get_windows (MetaScreen *screen);
ClutterActor * mutter_get_window_group_for_screen (MetaScreen *screen);
-void mutter_set_stage_input_region (MetaScreen *screen,
- XserverRegion region);
-void mutter_empty_stage_input_region (MetaScreen *screen);
-
#endif
diff --git a/src/include/mutter-window.h b/src/include/mutter-window.h
new file mode 100644
index 0000000..9ef3794
--- /dev/null
+++ b/src/include/mutter-window.h
@@ -0,0 +1,71 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2008 Matthew Allum
+ * Copyright (C) 2007 Iain Holmes
+ * Based on xcompmgr - (c) 2003 Keith Packard
+ * xfwm4 - (c) 2005-2007 Olivier Fourdan
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef MUTTER_WINDOW_H_
+#define MUTTER_WINDOW_H_
+
+#include <clutter/clutter.h>
+#include <X11/Xlib.h>
+
+#include "compositor.h"
+
+/*
+ * MutterWindow object (ClutterGroup sub-class)
+ */
+#define MUTTER_TYPE_COMP_WINDOW (mutter_window_get_type ())
+#define MUTTER_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindow))
+#define MUTTER_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
+#define MUTTER_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_TYPE_COMP_WINDOW))
+#define MUTTER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_COMP_WINDOW))
+#define MUTTER_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_COMP_WINDOW, MutterWindowClass))
+
+typedef struct _MutterWindow MutterWindow;
+typedef struct _MutterWindowClass MutterWindowClass;
+typedef struct _MutterWindowPrivate MutterWindowPrivate;
+
+struct _MutterWindowClass
+{
+ ClutterGroupClass parent_class;
+};
+
+struct _MutterWindow
+{
+ ClutterGroup parent;
+
+ MutterWindowPrivate *priv;
+};
+
+GType mutter_window_get_type (void);
+
+Window mutter_window_get_x_window (MutterWindow *mcw);
+MetaCompWindowType mutter_window_get_window_type (MutterWindow *mcw);
+gint mutter_window_get_workspace (MutterWindow *mcw);
+gboolean mutter_window_is_hidden (MutterWindow *mcw);
+MetaWindow * mutter_window_get_meta_window (MutterWindow *mcw);
+ClutterActor * mutter_window_get_texture (MutterWindow *mcw);
+gboolean mutter_window_is_override_redirect (MutterWindow *mcw);
+const char * mutter_window_get_description (MutterWindow *mcw);
+gboolean mutter_window_showing_on_its_workspace (MutterWindow *mcw);
+
+#endif /* MUTTER_WINDOW_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]