From c60d4c2bc43d374269f3148bc752a48b6033376a Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Fri, 26 Jun 2009 15:33:20 -0400 Subject: [PATCH] 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 | 1578 +----------------------- 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, 1726 insertions(+), 1591 deletions(-) create mode 100644 src/compositor/mutter-window-private.h create mode 100644 src/compositor/mutter-window.c create mode 100644 src/include/mutter-window.h diff --git a/src/Makefile.am b/src/Makefile.am index d46a73a26..e3a7c5cf3 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 6611761af..986c570b8 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 + #include "compositor.h" #include "display.h" +#include "mutter-plugin-manager.h" #include +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 5a70bb9cc..0950fa2ad 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -2,91 +2,24 @@ #include -#include -#include +#include -#include - -#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 -#include +#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 #include -#include -#include -#include - -#include - -#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) +mutter_switch_workspace_completed (MetaScreen *screen) { - 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; + MetaCompScreen *info = meta_screen_get_compositor_data (screen); - /* 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: + /* FIXME -- must redo stacking order */ + info->switch_workspace_in_progress--; + if (info->switch_workspace_in_progress < 0) { - 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; - } + g_warning ("Error in workspace_switch accounting!"); + info->switch_workspace_in_progress = 0; } - break; - case MUTTER_PLUGIN_MAP: - /* - * Make sure that the actor is at the correct place in case - * the plugin fscked. - */ - priv->map_in_progress--; - if (priv->map_in_progress < 0) - { - g_warning ("Error in map accounting."); - priv->map_in_progress = 0; - } - - 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; - } + if (!info->switch_workspace_in_progress) + mutter_finish_workspace_switch (info); } - void meta_compositor_destroy (MetaCompositor *compositor) { } -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; -} - -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; - - if (!info->plugin_mgr || - !mutter_plugin_manager_event_simple (info->plugin_mgr, - cw, - MUTTER_PLUGIN_DESTROY)) - { - priv->destroy_in_progress--; - - if (effect_in_progress (cw, FALSE)) - { - priv->needs_destroy = TRUE; - } - else - clutter_actor_destroy (CLUTTER_ACTOR (cw)); - } -} - -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; - } -} - -static void -unmap_win (MutterWindow *cw) -{ - 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 77143447c..18763dac8 100644 --- a/src/compositor/mutter-plugin.c +++ b/src/compositor/mutter-plugin.c @@ -31,6 +31,9 @@ #include #include +#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 000000000..68be514dc --- /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 +#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 000000000..3a950674c --- /dev/null +++ b/src/compositor/mutter-window.c @@ -0,0 +1,1528 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +#include +#include +#include +#include + +#include + +#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 7ab35115f..ba3ab0cf9 100644 --- a/src/include/compositor-mutter.h +++ b/src/include/compositor-mutter.h @@ -26,63 +26,17 @@ #define MUTTER_H_ #include -#include #include #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 000000000..9ef37944a --- /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 +#include + +#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 */