diff --git a/configure.in b/configure.in index b007892a0..bb2e11545 100644 --- a/configure.in +++ b/configure.in @@ -9,7 +9,7 @@ m4_define([metacity_micro_version], [55]) m4_define([metacity_version], [metacity_major_version.metacity_minor_version.metacity_micro_version]) -m4_define([metacity_clutter_plugin_api_version], [1]) +m4_define([metacity_clutter_plugin_api_version], [2]) AC_INIT([metacity], [metacity_version], [http://bugzilla.gnome.org/enter_bug.cgi?product=metacity]) diff --git a/src/Makefile.am b/src/Makefile.am index 8f935d278..795717e09 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -113,6 +113,9 @@ metacity_SOURCES += \ compositor/mutter/mutter-plugin-manager.h \ compositor/mutter/tidy/tidy-texture-frame.c \ compositor/mutter/tidy/tidy-texture-frame.h \ + compositor/mutter/mutter-module.c \ + compositor/mutter/mutter-module.h \ + compositor/mutter/mutter-plugin.c \ include/mutter-plugin.h endif diff --git a/src/compositor/mutter/compositor-mutter.c b/src/compositor/mutter/compositor-mutter.c index 815613234..2a9f7a3b8 100644 --- a/src/compositor/mutter/compositor-mutter.c +++ b/src/compositor/mutter/compositor-mutter.c @@ -60,7 +60,7 @@ __FILE__, __LINE__); } /* #define DEBUG_TRACE g_print */ -#define DEBUG_TRACE(X) +#define DEBUG_TRACE(X) /* * Register GType wrapper for XWindowAttributes, so we do not have to @@ -245,10 +245,11 @@ mutter_window_class_init (MutterWindowClass *klass) object_class->get_property = mutter_window_get_property; object_class->constructed = mutter_window_constructed; - pspec = g_param_spec_pointer ("meta-window", - "MetaWindow", - "MetaWindow", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + 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, @@ -425,7 +426,7 @@ mutter_window_set_property (GObject *object, switch (prop_id) { case PROP_MCW_META_WINDOW: - priv->window = g_value_get_pointer (value); + priv->window = g_value_get_object (value); break; case PROP_MCW_META_SCREEN: priv->screen = g_value_get_pointer (value); @@ -453,7 +454,7 @@ mutter_window_get_property (GObject *object, switch (prop_id) { case PROP_MCW_META_WINDOW: - g_value_set_pointer (value, priv->window); + g_value_set_object (value, priv->window); break; case PROP_MCW_META_SCREEN: g_value_set_pointer (value, priv->screen); @@ -783,7 +784,7 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) MetaScreen *screen = priv->screen; MetaCompScreen *info = meta_screen_get_compositor_data (screen); ClutterActor *actor = CLUTTER_ACTOR (cw); - + /* 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 */ @@ -904,7 +905,7 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) default: break; } - + switch (event) { case MUTTER_PLUGIN_MINIMIZE: @@ -968,7 +969,7 @@ destroy_win (MutterWindow *cw) MetaWindow *window; MetaCompScreen *info; MutterWindowPrivate *priv; - + priv = cw->priv; window = priv->window; @@ -1009,7 +1010,7 @@ destroy_win (MutterWindow *cw) MUTTER_PLUGIN_DESTROY)) { priv->destroy_in_progress--; - + if (priv->minimize_in_progress || priv->maximize_in_progress || priv->unmaximize_in_progress || @@ -1054,7 +1055,7 @@ map_win (MutterWindow *cw) { MutterWindowPrivate *priv; MetaCompScreen *info; - + if (!cw) return; @@ -1108,7 +1109,7 @@ unmap_win (MutterWindow *cw) { MutterWindowPrivate *priv; MetaCompScreen *info; - + if (!cw) return; @@ -1164,7 +1165,7 @@ add_win (MetaWindow *window) MetaFrame *frame; Window top_window; XWindowAttributes attrs; - + g_return_if_fail (info != NULL); frame = meta_window_get_frame (window); @@ -1608,7 +1609,7 @@ clutter_cmp_manage_screen (MetaCompositor *compositor, /* Check if the screen is already managed */ if (meta_screen_get_compositor_data (screen)) return; - + meta_error_trap_push_with_return (display); XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual); XSync (xdisplay, FALSE); @@ -1712,7 +1713,7 @@ clutter_cmp_remove_window (MetaCompositor *compositor, { #ifdef HAVE_COMPOSITE_EXTENSIONS MutterWindow *cw = NULL; - + DEBUG_TRACE ("clutter_cmp_remove_window\n"); cw = meta_window_get_compositor_private (window); if (!cw) @@ -1844,7 +1845,7 @@ clutter_cmp_map_window (MetaCompositor *compositor, MetaWindow *window) DEBUG_TRACE ("clutter_cmp_map_window\n"); if (!cw) return; - + map_win (cw); #endif } @@ -2005,6 +2006,10 @@ clutter_cmp_update_workspace_geometry (MetaCompositor *compositor, MetaWorkspace *workspace) { #ifdef HAVE_COMPOSITE_EXTENSIONS +#if 0 + /* FIXME -- should do away with this function in favour of MetaWorkspace + * signal. + */ MetaScreen *screen = meta_workspace_get_screen (workspace); MetaCompScreen *info; MutterPluginManager *mgr; @@ -2018,6 +2023,7 @@ clutter_cmp_update_workspace_geometry (MetaCompositor *compositor, mutter_plugin_manager_update_workspace (mgr, workspace); #endif +#endif } static void @@ -2105,7 +2111,7 @@ static void sync_actor_stacking (GList *windows) { GList *tmp; - + /* NB: The first entry in the list is stacked the lowest */ for (tmp = g_list_last (windows); tmp != NULL; tmp = tmp->prev) @@ -2191,7 +2197,7 @@ clutter_cmp_sync_window_geometry (MetaCompositor *compositor, return; sync_actor_position (cw); - + #endif } @@ -2208,7 +2214,7 @@ clutter_cmp_sync_screen_size (MetaCompositor *compositor, g_return_if_fail (info); clutter_actor_set_size (info->stage, width, height); - + meta_verbose ("Changed size for stage on screen %d to %dx%d\n", meta_screen_get_screen_number (screen), width, height); diff --git a/src/compositor/mutter/mutter-module.c b/src/compositor/mutter/mutter-module.c new file mode 100644 index 000000000..d965b8d23 --- /dev/null +++ b/src/compositor/mutter/mutter-module.c @@ -0,0 +1,206 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (c) 2008 Intel Corp. + * + * Author: Tomas Frydrych + * + * 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. + */ + +#include "mutter-plugin.h" +#include "mutter-module.h" + +#include + +enum +{ + PROP_0, + PROP_PATH, +}; + +struct _MutterModulePrivate +{ + GModule *lib; + gchar *path; + GType plugin_type; +}; + +#define MUTTER_MODULE_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_MODULE, MutterModulePrivate)) + +G_DEFINE_TYPE (MutterModule, mutter_module, G_TYPE_TYPE_MODULE); + +static gboolean +mutter_module_load (GTypeModule *gmodule) +{ + MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv; + MutterPluginVersion *info = NULL; + GType (*register_type) (GTypeModule *) = NULL; + + if (priv->lib && priv->plugin_type) + return TRUE; + + g_assert (priv->path); + + if (!priv->lib && + !(priv->lib = g_module_open (priv->path, G_MODULE_BIND_LOCAL))) + { + g_warning ("Could not load library [%s]", priv->path); + return FALSE; + } + + if (g_module_symbol (priv->lib, "mutter_plugin_version", (gpointer *)&info) && + g_module_symbol (priv->lib, "mutter_plugin_register_type", + (gpointer *)®ister_type) && + info && register_type) + { + if (info->version_api != METACITY_CLUTTER_PLUGIN_API_VERSION) + g_warning ("Plugin API mismatch for [%s]", priv->path); + else + { + GType plugin_type; + + if (!(plugin_type = register_type (gmodule))) + { + g_warning ("Could not register type for plugin %s", + priv->path); + return FALSE; + } + else + { + priv->plugin_type = plugin_type; + } + + return TRUE; + } + } + else + g_warning ("Broken plugin module [%s]", priv->path); + + return FALSE; +} + +static void +mutter_module_unload (GTypeModule *gmodule) +{ + MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv; + + g_module_close (priv->lib); + + priv->lib = NULL; + priv->plugin_type = 0; +} + +static void +mutter_module_dispose (GObject *object) +{ + G_OBJECT_CLASS (mutter_module_parent_class)->dispose (object); +} + +static void +mutter_module_finalize (GObject *object) +{ + MutterModulePrivate *priv = MUTTER_MODULE (object)->priv; + + g_free (priv->path); + priv->path = NULL; + + G_OBJECT_CLASS (mutter_module_parent_class)->finalize (object); +} + +static void +mutter_module_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MutterModulePrivate *priv = MUTTER_MODULE (object)->priv; + + switch (prop_id) + { + case PROP_PATH: + g_free (priv->path); + priv->path = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mutter_module_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MutterModulePrivate *priv = MUTTER_MODULE (object)->priv; + + switch (prop_id) + { + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mutter_module_class_init (MutterModuleClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GTypeModuleClass *gmodule_class = G_TYPE_MODULE_CLASS (klass); + + gobject_class->finalize = mutter_module_finalize; + gobject_class->dispose = mutter_module_dispose; + gobject_class->set_property = mutter_module_set_property; + gobject_class->get_property = mutter_module_get_property; + + gmodule_class->load = mutter_module_load; + gmodule_class->unload = mutter_module_unload; + + g_object_class_install_property (gobject_class, + PROP_PATH, + g_param_spec_string ("path", + "Path", + "Load path", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (gobject_class, sizeof (MutterModulePrivate)); +} + +static void +mutter_module_init (MutterModule *self) +{ + MutterModulePrivate *priv; + + self->priv = priv = MUTTER_MODULE_GET_PRIVATE (self); + +} + +GType +mutter_module_get_plugin_type (MutterModule *module) +{ + MutterModulePrivate *priv = MUTTER_MODULE (module)->priv; + + return priv->plugin_type; +} + diff --git a/src/compositor/mutter/mutter-module.h b/src/compositor/mutter/mutter-module.h new file mode 100644 index 000000000..07265d097 --- /dev/null +++ b/src/compositor/mutter/mutter-module.h @@ -0,0 +1,57 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (c) 2008 Intel Corp. + * + * Author: Tomas Frydrych + * + * 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_MODULE_H_ +#define MUTTER_MODULE_H_ + +#include + +#define MUTTER_TYPE_MODULE (mutter_module_get_type ()) +#define MUTTER_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_MODULE, MutterModule)) +#define MUTTER_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_MODULE, MutterModuleClass)) +#define MUTTER_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_MODULE_TYPE)) +#define MUTTER_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_MODULE)) +#define MUTTER_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_MODULE, MutterModuleClass)) + +typedef struct _MutterModule MutterModule; +typedef struct _MutterModuleClass MutterModuleClass; +typedef struct _MutterModulePrivate MutterModulePrivate; + +struct _MutterModule +{ + GTypeModule parent; + + MutterModulePrivate *priv; +}; + +struct _MutterModuleClass +{ + GTypeModuleClass parent_class; +}; + + +GType mutter_module_get_type (void); + +GType mutter_module_get_plugin_type (MutterModule *module); + +#endif diff --git a/src/compositor/mutter/mutter-plugin-manager.c b/src/compositor/mutter/mutter-plugin-manager.c index 4f936834f..4d89dbba8 100644 --- a/src/compositor/mutter/mutter-plugin-manager.c +++ b/src/compositor/mutter/mutter-plugin-manager.c @@ -26,215 +26,52 @@ #include "prefs.h" #include "errors.h" #include "workspace.h" +#include "mutter-module.h" -#include #include -#include -#include -#include -#include -static gboolean mutter_plugin_manager_reload ( - MutterPluginManager *plugin_mgr); +/* + * There is only one instace of each module per the process. + */ +static GHashTable *plugin_modules = NULL; + +static gboolean mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr); struct MutterPluginManager { MetaScreen *screen; - GList *plugins; /* TODO -- maybe use hash table */ + GList *plugins; GList *unload; /* Plugins that are disabled and pending unload */ guint idle_unload_id; }; -typedef struct MutterPluginPrivate -{ - char *name; - MutterPluginManager *self; - GModule *module; - gulong features; - /* We use this to track the number of effects currently being managed - * by a plugin. Currently this is used to block unloading while effects - * are in progress. */ - gint running; - - gboolean disabled : 1; -} MutterPluginPrivate; - - -static void -free_plugin_workspaces (MutterPlugin *plugin) -{ - GList *l; - - l = plugin->work_areas; - - while (l) - { - g_free (l->data); - l = l->next; - } - - if (plugin->work_areas) - g_list_free (plugin->work_areas); - - plugin->work_areas = NULL; -} - -/* - * Gets work area geometry and stores it in list in the plugin. - * - * If the plugin list is already populated, we simply replace it (we are - * dealing with a small number of items in the list and unfrequent changes). - */ -static void -update_plugin_workspaces (MetaScreen *screen, - MutterPlugin *plugin) -{ - GList *l, *l2 = NULL; - - l = meta_screen_get_workspaces (screen); - - while (l) - { - MetaWorkspace *w = l->data; - MetaRectangle *r; - - r = g_new0 (MetaRectangle, 1); - - meta_workspace_get_work_area_all_xineramas (w, (MetaRectangle*)r); - - l2 = g_list_append (l2, r); - - l = l->next; - } - - free_plugin_workspaces (plugin); - - plugin->work_areas = l2; -} - -/** - * parse_disable_params: - * @params: as read from gconf, a ':' seperated list of plugin options - * @features: The mask of features the plugin advertises - * - * This function returns a new mask of features removing anything that - * the user has disabled. - */ -static gulong -parse_disable_params (const char *params, MutterPlugin *plugin) -{ - char *p; - gulong features = 0; - -/* - * Feature flags: identify events that the plugin can handle; a plugin can - * handle one or more events. - */ - if (plugin->minimize) - features |= MUTTER_PLUGIN_MINIMIZE; - - if (plugin->maximize) - features |= MUTTER_PLUGIN_MAXIMIZE; - - if (plugin->unmaximize) - features |= MUTTER_PLUGIN_UNMAXIMIZE; - - if (plugin->map) - features |= MUTTER_PLUGIN_MAP; - - if (plugin->destroy) - features |= MUTTER_PLUGIN_DESTROY; - - if (plugin->switch_workspace) - features |= MUTTER_PLUGIN_SWITCH_WORKSPACE; - - if (!params) - return features; - - if ((p = strstr (params, "disable:"))) - { - gchar *d = g_strdup (p+8); - - p = strchr (d, ';'); - - if (p) - *p = 0; - - if (strstr (d, "minimize")) - features &= ~ MUTTER_PLUGIN_MINIMIZE; - - if (strstr (d, "maximize")) - features &= ~ MUTTER_PLUGIN_MAXIMIZE; - - if (strstr (d, "unmaximize")) - features &= ~ MUTTER_PLUGIN_UNMAXIMIZE; - - if (strstr (d, "map")) - features &= ~ MUTTER_PLUGIN_MAP; - - if (strstr (d, "destroy")) - features &= ~ MUTTER_PLUGIN_DESTROY; - - if (strstr (d, "switch-workspace")) - features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE; - - g_free (d); - } - return features; -} /* * Checks that the plugin is compatible with the WM and sets up the plugin * struct. */ static MutterPlugin * -mutter_plugin_load (MutterPluginManager *plugin_mgr, - GModule *module, +mutter_plugin_load (MutterPluginManager *mgr, + MutterModule *module, const gchar *params) { - MutterPlugin *plugin; + MutterPlugin *plugin = NULL; + GType plugin_type = mutter_module_get_plugin_type (module); - if (g_module_symbol (module, "mutter_plugin", (gpointer *)&plugin)) + if (!plugin_type) { - if (plugin->version_api == METACITY_CLUTTER_PLUGIN_API_VERSION) - { - MutterPluginPrivate *priv; - - priv = g_new0 (MutterPluginPrivate, 1); - priv->name = _(plugin->name); - priv->module = module; - priv->self = plugin_mgr; - - /* FIXME: instead of hanging private data of the plugin descriptor - * we could make the descriptor const if we were to hang it off - * a plugin manager structure */ - plugin->manager_private = priv; - - update_plugin_workspaces (plugin_mgr->screen, plugin); - - priv->features = parse_disable_params (params, plugin); - - /* - * Check for and run the plugin init function. - */ - if (!plugin->do_init || !(plugin->do_init (params))) - { - g_free (priv); - - free_plugin_workspaces (plugin); - - return NULL; - } - - meta_verbose ("Loaded plugin [%s]\n", priv->name); - - return plugin; - } + g_warning ("Plugin type not registered !!!"); + return NULL; } - return NULL; + plugin = g_object_new (plugin_type, + "screen", mgr->screen, + "params", params, + NULL); + + return plugin; } /* @@ -245,22 +82,13 @@ mutter_plugin_load (MutterPluginManager *plugin_mgr, static gboolean mutter_plugin_unload (MutterPlugin *plugin) { - MutterPluginPrivate *priv; - GModule *module; - - priv = plugin->manager_private; - module = priv->module; - - if (priv->running) + if (mutter_plugin_running (plugin)) { - priv->disabled = TRUE; + g_object_set (plugin, "disabled", TRUE, NULL); return FALSE; } - g_free (priv); - plugin->manager_private = NULL; - - g_module_close (module); + g_object_unref (plugin); return TRUE; } @@ -353,10 +181,20 @@ prefs_changed_callback (MetaPreference pref, { mutter_plugin_manager_reload (plugin_mgr); } - else if (pref == META_PREF_NUM_WORKSPACES) +} + +static MutterModule * +mutter_plugin_manager_get_module (const gchar *path) +{ + MutterModule *module = g_hash_table_lookup (plugin_modules, path); + + if (!module && + (module = g_object_new (MUTTER_TYPE_MODULE, "path", path, NULL))) { - mutter_plugin_manager_update_workspaces (plugin_mgr); + g_hash_table_insert (plugin_modules, g_strdup (path), module); } + + return module; } /* @@ -388,8 +226,8 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr) if (plugin_string) { - GModule *plugin; - gchar *path; + MutterModule *module; + gchar *path; params = strchr (plugin_string, ':'); @@ -404,20 +242,35 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr) else path = g_strconcat (dpath, plugin_string, ".so", NULL); - if ((plugin = g_module_open (path, G_MODULE_BIND_LOCAL))) + module = mutter_plugin_manager_get_module (path); + + if (module) { MutterPlugin *p; - if ((p = mutter_plugin_load (plugin_mgr, plugin, params))) - plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p); + /* + * This dlopens the module and registers the plugin type with the + * GType system, if the module is not already loaded. When we + * create a plugin, the type system also calls g_type_module_use() + * to guarantee the module will not be unloaded during the plugin + * life time. Consequently we can unuse() the module again. + */ + g_type_module_use (G_TYPE_MODULE (module)); + + if ((p = mutter_plugin_load (plugin_mgr, module, params))) + { + plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p); + } else { - g_message ("Plugin load for [%s] failed", path); - g_module_close (plugin); + g_warning ("Plugin load for [%s] failed", path); } + + g_type_module_unuse (G_TYPE_MODULE (module)); } else - g_message ("Unable to load plugin [%s]: %s", path, g_module_error()); + g_warning ("Unable to load plugin module [%s]: %s", + path, g_module_error()); g_free (path); g_free (plugin_string); @@ -459,57 +312,17 @@ mutter_plugin_manager_init (MutterPluginManager *plugin_mgr) return mutter_plugin_manager_load (plugin_mgr); } -void -mutter_plugin_manager_update_workspace (MutterPluginManager *plugin_mgr, - MetaWorkspace *workspace) -{ - GList *l; - gint index; - - index = meta_workspace_index (workspace); - l = plugin_mgr->plugins; - - while (l) - { - MutterPlugin *plugin = l->data; - MetaRectangle *rect = g_list_nth_data (plugin->work_areas, index); - - if (rect) - { - meta_workspace_get_work_area_all_xineramas (workspace, rect); - } - else - { - /* Something not entirely right; redo the whole thing */ - update_plugin_workspaces (plugin_mgr->screen, plugin); - return; - } - - l = l->next; - } -} - -void -mutter_plugin_manager_update_workspaces (MutterPluginManager *plugin_mgr) -{ - GList *l; - - l = plugin_mgr->plugins; - while (l) - { - MutterPlugin *plugin = l->data; - - update_plugin_workspaces (plugin_mgr->screen, plugin); - - l = l->next; - } -} - MutterPluginManager * mutter_plugin_manager_new (MetaScreen *screen) { MutterPluginManager *plugin_mgr; + if (!plugin_modules) + { + plugin_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + NULL); + } + plugin_mgr = g_new0 (MutterPluginManager, 1); plugin_mgr->screen = screen; @@ -533,12 +346,12 @@ mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr, while (l) { MutterPlugin *plugin = l->data; - MutterPluginPrivate *priv = plugin->manager_private; + MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin); - if (!priv->disabled - && (priv->features & events) - && plugin->kill_effect) - plugin->kill_effect (actor, events); + if (!mutter_plugin_disabled (plugin) + && (mutter_plugin_features (plugin) & events) + && klass->kill_effect) + klass->kill_effect (plugin, actor, events); l = l->next; } @@ -567,43 +380,41 @@ mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr, while (l) { MutterPlugin *plugin = l->data; - MutterPluginPrivate *priv = plugin->manager_private; + MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin); - if (!priv->disabled && (priv->features & event)) + if (!mutter_plugin_disabled (plugin) && + (mutter_plugin_features (plugin) & event)) { retval = TRUE; switch (event) { case MUTTER_PLUGIN_MINIMIZE: - if (plugin->minimize) + if (klass->minimize) { mutter_plugin_manager_kill_effect ( plugin_mgr, actor, ALL_BUT_SWITCH); - priv->running++; - plugin->minimize (actor); + klass->minimize (plugin, actor); } break; case MUTTER_PLUGIN_MAP: - if (plugin->map) + if (klass->map) { mutter_plugin_manager_kill_effect ( plugin_mgr, actor, ALL_BUT_SWITCH); - priv->running++; - plugin->map (actor); + klass->map (plugin, actor); } break; case MUTTER_PLUGIN_DESTROY: - if (plugin->destroy) + if (klass->destroy) { - priv->running++; - plugin->destroy (actor); + klass->destroy (plugin, actor); } break; default: @@ -641,37 +452,38 @@ mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr, while (l) { MutterPlugin *plugin = l->data; - MutterPluginPrivate *priv = plugin->manager_private; + MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin); - if (!priv->disabled && (priv->features & event)) + if (!mutter_plugin_disabled (plugin) && + (mutter_plugin_features (plugin) & event)) { retval = TRUE; switch (event) { case MUTTER_PLUGIN_MAXIMIZE: - if (plugin->maximize) + if (klass->maximize) { mutter_plugin_manager_kill_effect ( plugin_mgr, actor, ALL_BUT_SWITCH); - plugin->maximize (actor, - target_x, target_y, - target_width, target_height); + klass->maximize (plugin, actor, + target_x, target_y, + target_width, target_height); } break; case MUTTER_PLUGIN_UNMAXIMIZE: - if (plugin->unmaximize) + if (klass->unmaximize) { mutter_plugin_manager_kill_effect ( plugin_mgr, actor, ALL_BUT_SWITCH); - plugin->unmaximize (actor, - target_x, target_y, - target_width, target_height); + klass->unmaximize (plugin, actor, + target_x, target_y, + target_width, target_height); } break; default: @@ -706,13 +518,13 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr, while (l) { MutterPlugin *plugin = l->data; - MutterPluginPrivate *priv = plugin->manager_private; + MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin); - if (!priv->disabled && - (priv->features & MUTTER_PLUGIN_SWITCH_WORKSPACE) && + if (!mutter_plugin_disabled (plugin) && + (mutter_plugin_features (plugin) & MUTTER_PLUGIN_SWITCH_WORKSPACE) && (actors && *actors)) { - if (plugin->switch_workspace) + if (klass->switch_workspace) { retval = TRUE; mutter_plugin_manager_kill_effect ( @@ -720,7 +532,7 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr, MUTTER_WINDOW ((*actors)->data), MUTTER_PLUGIN_SWITCH_WORKSPACE); - plugin->switch_workspace (actors, from, to, direction); + klass->switch_workspace (plugin, actors, from, to, direction); } } @@ -751,11 +563,12 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr, while (l) { - MutterPlugin *plugin = l->data; + MutterPlugin *plugin = l->data; + MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin); - if (plugin->xevent_filter) + if (klass->xevent_filter) { - if (plugin->xevent_filter (xev) == TRUE) + if (klass->xevent_filter (plugin, xev) == TRUE) return TRUE; } @@ -765,176 +578,3 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr, return FALSE; } -/* - * Public accessors for plugins, exposed from mutter-plugin.h - */ -ClutterActor * -mutter_plugin_get_overlay_group (MutterPlugin *plugin) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *plugin_mgr = priv->self; - - return mutter_get_overlay_group_for_screen (plugin_mgr->screen); -} - -ClutterActor * -mutter_plugin_get_stage (MutterPlugin *plugin) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *plugin_mgr = priv->self; - - return mutter_get_stage_for_screen (plugin_mgr->screen); -} - -ClutterActor * -mutter_plugin_get_window_group (MutterPlugin *plugin) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *plugin_mgr = priv->self; - - return mutter_get_window_group_for_screen (plugin_mgr->screen); -} - -void -mutter_plugin_effect_completed (MutterPlugin *plugin, - MutterWindow *actor, - unsigned long event) -{ - MutterPluginPrivate *priv = plugin->manager_private; - - priv->running--; - - if (!actor) - { - g_warning ("Plugin [%s] passed NULL for actor!", - (plugin && plugin->name) ? plugin->name : "unknown"); - } - - mutter_window_effect_completed (actor, event); -} - -void -mutter_plugin_query_screen_size (MutterPlugin *plugin, - int *width, - int *height) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *plugin_mgr = priv->self; - - meta_screen_get_size (plugin_mgr->screen, width, height); -} - -void -mutter_plugin_set_stage_reactive (MutterPlugin *plugin, - gboolean reactive) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *mgr = priv->self; - MetaDisplay *display = meta_screen_get_display (mgr->screen); - Display *xdpy = meta_display_get_xdisplay (display); - Window xstage, xoverlay; - ClutterActor *stage; - - stage = mutter_get_stage_for_screen (mgr->screen); - xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); - xoverlay = mutter_get_overlay_window (mgr->screen); - - static XserverRegion region = None; - - if (region == None) - region = XFixesCreateRegion (xdpy, NULL, 0); - - if (reactive) - { - XFixesSetWindowShapeRegion (xdpy, xstage, - ShapeInput, 0, 0, None); - XFixesSetWindowShapeRegion (xdpy, xoverlay, - ShapeInput, 0, 0, None); - } - else - { - XFixesSetWindowShapeRegion (xdpy, xstage, - ShapeInput, 0, 0, region); - XFixesSetWindowShapeRegion (xdpy, xoverlay, - ShapeInput, 0, 0, region); - } -} - -void -mutter_plugin_set_stage_input_area (MutterPlugin *plugin, - gint x, gint y, gint width, gint height) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *mgr = priv->self; - MetaDisplay *display = meta_screen_get_display (mgr->screen); - Display *xdpy = meta_display_get_xdisplay (display); - Window xstage, xoverlay; - ClutterActor *stage; - XRectangle rect; - XserverRegion region; - - stage = mutter_get_stage_for_screen (mgr->screen); - xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); - xoverlay = mutter_get_overlay_window (mgr->screen); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - - region = XFixesCreateRegion (xdpy, &rect, 1); - - XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region); - XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region); - - XFixesDestroyRegion (xdpy, region); -} - -void -mutter_plugin_set_stage_input_region (MutterPlugin *plugin, - XserverRegion region) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *mgr = priv->self; - MetaDisplay *display = meta_screen_get_display (mgr->screen); - Display *xdpy = meta_display_get_xdisplay (display); - Window xstage, xoverlay; - ClutterActor *stage; - - stage = mutter_get_stage_for_screen (mgr->screen); - xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); - xoverlay = mutter_get_overlay_window (mgr->screen); - - XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region); - XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region); -} - -GList * -mutter_plugin_get_windows (MutterPlugin *plugin) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *plugin_mgr = priv->self; - - return mutter_get_windows (plugin_mgr->screen); -} - -Display * -mutter_plugin_get_xdisplay (MutterPlugin *plugin) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *mgr = priv->self; - MetaDisplay *display = meta_screen_get_display (mgr->screen); - Display *xdpy = meta_display_get_xdisplay (display); - - return xdpy; -} - -MetaScreen * -mutter_plugin_get_screen (MutterPlugin *plugin) -{ - MutterPluginPrivate *priv = plugin->manager_private; - MutterPluginManager *mgr = priv->self; - - return mgr->screen; -} - diff --git a/src/compositor/mutter/mutter-plugin.c b/src/compositor/mutter/mutter-plugin.c new file mode 100644 index 000000000..32a6b1fca --- /dev/null +++ b/src/compositor/mutter/mutter-plugin.c @@ -0,0 +1,574 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (c) 2008 Intel Corp. + * + * Author: Tomas Frydrych + * + * 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. + */ + +#include "mutter-plugin.h" +#include "screen.h" +#include "display.h" + +#include +#include +#include +#include +#include + +G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT); + +#define MUTTER_PLUGIN_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_PLUGIN, MutterPluginPrivate)) + +enum +{ + PROP_0, + PROP_SCREEN, + PROP_PARAMS, + PROP_FEATURES, + PROP_DISABLED, + PROP_DEBUG_MODE, +}; + +struct _MutterPluginPrivate +{ + MetaScreen *screen; + gchar *params; + gulong features; + + gint running; + + gboolean disabled : 1; + gboolean debug : 1; +}; + +static void +mutter_plugin_dispose (GObject *object) +{ + G_OBJECT_CLASS (mutter_plugin_parent_class)->dispose (object); +} + +static void +mutter_plugin_finalize (GObject *object) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv; + + g_free (priv->params); + priv->params = NULL; + + G_OBJECT_CLASS (mutter_plugin_parent_class)->finalize (object); +} + +static void +mutter_plugin_parse_params (MutterPlugin *plugin) +{ + char *p; + gulong features = 0; + MutterPluginPrivate *priv = plugin->priv; + MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin); + +/* + * Feature flags: identify events that the plugin can handle; a plugin can + * handle one or more events. + */ + if (klass->minimize) + features |= MUTTER_PLUGIN_MINIMIZE; + + if (klass->maximize) + features |= MUTTER_PLUGIN_MAXIMIZE; + + if (klass->unmaximize) + features |= MUTTER_PLUGIN_UNMAXIMIZE; + + if (klass->map) + features |= MUTTER_PLUGIN_MAP; + + if (klass->destroy) + features |= MUTTER_PLUGIN_DESTROY; + + if (klass->switch_workspace) + features |= MUTTER_PLUGIN_SWITCH_WORKSPACE; + + if (priv->params) + { + gboolean debug = FALSE; + + if ((p = strstr (priv->params, "disable:"))) + { + gchar *d = g_strdup (p+8); + + p = strchr (d, ';'); + + if (p) + *p = 0; + + if (strstr (d, "minimize")) + features &= ~ MUTTER_PLUGIN_MINIMIZE; + + if (strstr (d, "maximize")) + features &= ~ MUTTER_PLUGIN_MAXIMIZE; + + if (strstr (d, "unmaximize")) + features &= ~ MUTTER_PLUGIN_UNMAXIMIZE; + + if (strstr (d, "map")) + features &= ~ MUTTER_PLUGIN_MAP; + + if (strstr (d, "destroy")) + features &= ~ MUTTER_PLUGIN_DESTROY; + + if (strstr (d, "switch-workspace")) + features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE; + + g_free (d); + } + + if (strstr (priv->params, "debug")) + debug = TRUE; + + if (debug != priv->debug) + { + priv->debug = debug; + + g_object_notify (G_OBJECT (plugin), "debug-mode"); + } + } + + if (features != priv->features) + { + priv->features = features; + + g_object_notify (G_OBJECT (plugin), "features"); + } +} + +static void +mutter_plugin_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv; + + switch (prop_id) + { + case PROP_SCREEN: + priv->screen = g_value_get_object (value); + break; + case PROP_PARAMS: + priv->params = g_value_dup_string (value); + mutter_plugin_parse_params (MUTTER_PLUGIN (object)); + break; + case PROP_DISABLED: + priv->disabled = g_value_get_boolean (value); + break; + case PROP_DEBUG_MODE: + priv->debug = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mutter_plugin_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv; + + switch (prop_id) + { + case PROP_SCREEN: + g_value_set_object (value, priv->screen); + break; + case PROP_PARAMS: + g_value_set_string (value, priv->params); + break; + case PROP_DISABLED: + g_value_set_boolean (value, priv->disabled); + break; + case PROP_DEBUG_MODE: + g_value_set_boolean (value, priv->debug); + break; + case PROP_FEATURES: + g_value_set_ulong (value, priv->features); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mutter_plugin_real_minimize (MutterPlugin *plugin, MutterWindow *actor) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + priv->running++; +} + +static void +mutter_plugin_real_maximize (MutterPlugin *plugin, + MutterWindow *actor, + gint x, + gint y, + gint width, + gint height) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + priv->running++; +} + + +static void +mutter_plugin_real_unmaximize (MutterPlugin *plugin, + MutterWindow *actor, + gint x, + gint y, + gint width, + gint height) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + priv->running++; +} + + +static void +mutter_plugin_real_map (MutterPlugin *plugin, MutterWindow *actor) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + priv->running++; +} + + +static void +mutter_plugin_real_destroy (MutterPlugin *plugin, MutterWindow *actor) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + priv->running++; +} + + +static void +mutter_plugin_real_switch_workspace (MutterPlugin *plugin, + const GList **actors, + gint from, + gint to, + MetaMotionDirection direction) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + priv->running++; +} + + +static void +mutter_plugin_class_init (MutterPluginClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass); + + gobject_class->finalize = mutter_plugin_finalize; + gobject_class->dispose = mutter_plugin_dispose; + gobject_class->set_property = mutter_plugin_set_property; + gobject_class->get_property = mutter_plugin_get_property; + + plugin_class->map = mutter_plugin_real_map; + plugin_class->minimize = mutter_plugin_real_minimize; + plugin_class->maximize = mutter_plugin_real_maximize; + plugin_class->unmaximize = mutter_plugin_real_unmaximize; + plugin_class->destroy = mutter_plugin_real_destroy; + plugin_class->switch_workspace = mutter_plugin_real_switch_workspace; + + g_object_class_install_property (gobject_class, + PROP_SCREEN, + g_param_spec_object ("screen", + "MetaScreen", + "MetaScreen", + META_TYPE_SCREEN, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_PARAMS, + g_param_spec_string ("params", + "Parameters", + "Plugin Parameters", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, + PROP_FEATURES, + g_param_spec_ulong ("features", + "Features", + "Plugin Features", + 0 , G_MAXULONG, 0, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_DISABLED, + g_param_spec_boolean ("disabled", + "Plugin disabled", + "Plugin disabled", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_DEBUG_MODE, + g_param_spec_boolean ("debug-mode", + "Debug Mode", + "Debug Mode", + FALSE, + G_PARAM_READABLE)); + + g_type_class_add_private (gobject_class, sizeof (MutterPluginPrivate)); +} + +static void +mutter_plugin_init (MutterPlugin *self) +{ + MutterPluginPrivate *priv; + + self->priv = priv = MUTTER_PLUGIN_GET_PRIVATE (self); +} + +gulong +mutter_plugin_features (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return priv->features; +} + +gboolean +mutter_plugin_disabled (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return priv->disabled; +} + +gboolean +mutter_plugin_running (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return (priv->running > 0); +} + +gboolean +mutter_plugin_debug_mode (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return priv->debug; +} + +const MutterPluginInfo * +mutter_plugin_get_info (MutterPlugin *plugin) +{ + MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin); + + if (klass && klass->plugin_info) + return klass->plugin_info (plugin); + + return NULL; +} + +ClutterActor * +mutter_plugin_get_overlay_group (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return mutter_get_overlay_group_for_screen (priv->screen); +} + +ClutterActor * +mutter_plugin_get_stage (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return mutter_get_stage_for_screen (priv->screen); +} + +ClutterActor * +mutter_plugin_get_window_group (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return mutter_get_window_group_for_screen (priv->screen); +} + +void +mutter_plugin_effect_completed (MutterPlugin *plugin, + MutterWindow *actor, + unsigned long event) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + if (priv->running-- < 0) + { + g_warning ("Error in running effect accounting, adjusting."); + priv->running = 0; + } + + if (!actor) + { + const MutterPluginInfo *info; + const gchar *name = NULL; + + if (plugin && (info = mutter_plugin_get_info (plugin))) + name = info->name; + + g_warning ("Plugin [%s] passed NULL for actor!", + name ? name : "unknown"); + } + + mutter_window_effect_completed (actor, event); +} + +void +mutter_plugin_query_screen_size (MutterPlugin *plugin, + int *width, + int *height) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + meta_screen_get_size (priv->screen, width, height); +} + +void +mutter_plugin_set_stage_reactive (MutterPlugin *plugin, + gboolean reactive) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + MetaScreen *screen = priv->screen; + MetaDisplay *display = meta_screen_get_display (screen); + Display *xdpy = meta_display_get_xdisplay (display); + Window xstage, xoverlay; + ClutterActor *stage; + + stage = mutter_get_stage_for_screen (screen); + xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); + xoverlay = mutter_get_overlay_window (screen); + + static XserverRegion region = None; + + if (region == None) + region = XFixesCreateRegion (xdpy, NULL, 0); + + if (reactive) + { + XFixesSetWindowShapeRegion (xdpy, xstage, + ShapeInput, 0, 0, None); + XFixesSetWindowShapeRegion (xdpy, xoverlay, + ShapeInput, 0, 0, None); + } + else + { + XFixesSetWindowShapeRegion (xdpy, xstage, + ShapeInput, 0, 0, region); + XFixesSetWindowShapeRegion (xdpy, xoverlay, + ShapeInput, 0, 0, region); + } +} + +void +mutter_plugin_set_stage_input_area (MutterPlugin *plugin, + gint x, gint y, gint width, gint height) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + MetaScreen *screen = priv->screen; + MetaDisplay *display = meta_screen_get_display (screen); + Display *xdpy = meta_display_get_xdisplay (display); + Window xstage, xoverlay; + ClutterActor *stage; + XRectangle rect; + XserverRegion region; + + stage = mutter_get_stage_for_screen (screen); + xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); + xoverlay = mutter_get_overlay_window (screen); + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + + region = XFixesCreateRegion (xdpy, &rect, 1); + + XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region); + XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region); + + XFixesDestroyRegion (xdpy, region); +} + +void +mutter_plugin_set_stage_input_region (MutterPlugin *plugin, + XserverRegion region) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + MetaScreen *screen = priv->screen; + MetaDisplay *display = meta_screen_get_display (screen); + Display *xdpy = meta_display_get_xdisplay (display); + Window xstage, xoverlay; + ClutterActor *stage; + + stage = mutter_get_stage_for_screen (screen); + xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); + xoverlay = mutter_get_overlay_window (screen); + + XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region); + XFixesSetWindowShapeRegion (xdpy, xoverlay, ShapeInput, 0, 0, region); +} + +GList * +mutter_plugin_get_windows (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return mutter_get_windows (priv->screen); +} + +Display * +mutter_plugin_get_xdisplay (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + MetaDisplay *display = meta_screen_get_display (priv->screen); + Display *xdpy = meta_display_get_xdisplay (display); + + return xdpy; +} + +MetaScreen * +mutter_plugin_get_screen (MutterPlugin *plugin) +{ + MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv; + + return priv->screen; +} + diff --git a/src/compositor/mutter/plugins/default.c b/src/compositor/mutter/plugins/default.c index a459e842a..7e4702f95 100644 --- a/src/compositor/mutter/plugins/default.c +++ b/src/compositor/mutter/plugins/default.c @@ -21,7 +21,6 @@ * 02111-1307, USA. */ -#define MUTTER_BUILDING_PLUGIN 1 #include "mutter-plugin.h" #include @@ -39,35 +38,63 @@ #define SWITCH_TIMEOUT 500 #define ACTOR_DATA_KEY "MCCP-Default-actor-data" + +#define MUTTER_TYPE_DEFAULT_PLUGIN (mutter_default_plugin_get_type ()) +#define MUTTER_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPlugin)) +#define MUTTER_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass)) +#define MUTTER_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_DEFAULT_PLUGIN_TYPE)) +#define MUTTER_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_DEFAULT_PLUGIN)) +#define MUTTER_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass)) + +#define MUTTER_DEFAULT_PLUGIN_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginPrivate)) + +typedef struct _MutterDefaultPlugin MutterDefaultPlugin; +typedef struct _MutterDefaultPluginClass MutterDefaultPluginClass; +typedef struct _MutterDefaultPluginPrivate MutterDefaultPluginPrivate; + +struct _MutterDefaultPlugin +{ + MutterPlugin parent; + + MutterDefaultPluginPrivate *priv; +}; + +struct _MutterDefaultPluginClass +{ + MutterPluginClass parent_class; +}; + static GQuark actor_data_quark = 0; -static gboolean do_init (const char *params); -static void minimize (MutterWindow *actor); -static void map (MutterWindow *actor); -static void destroy (MutterWindow *actor); -static void maximize (MutterWindow *actor, +static void minimize (MutterPlugin *plugin, + MutterWindow *actor); +static void map (MutterPlugin *plugin, + MutterWindow *actor); +static void destroy (MutterPlugin *plugin, + MutterWindow *actor); +static void maximize (MutterPlugin *plugin, + MutterWindow *actor, gint x, gint y, gint width, gint height); -static void unmaximize (MutterWindow *actor, +static void unmaximize (MutterPlugin *plugin, + MutterWindow *actor, gint x, gint y, gint width, gint height); -static void switch_workspace (const GList **actors, gint from, gint to, +static void switch_workspace (MutterPlugin *plugin, + const GList **actors, gint from, gint to, MetaMotionDirection direction); -static void kill_effect (MutterWindow *actor, gulong event); +static void kill_effect (MutterPlugin *plugin, + MutterWindow *actor, gulong event); -static gboolean reload (const char *params); +static const MutterPluginInfo * plugin_info (MutterPlugin *plugin); - -/* - * Create the plugin struct; function pointers initialized in - * g_module_check_init(). - */ -MUTTER_DECLARE_PLUGIN(); +MUTTER_PLUGIN_DECLARE(MutterDefaultPlugin, mutter_default_plugin); /* * Plugin private data that we store in the .plugin_private member. */ -typedef struct _PluginState +struct _MutterDefaultPluginPrivate { ClutterEffectTemplate *destroy_effect; ClutterEffectTemplate *minimize_effect; @@ -82,8 +109,150 @@ typedef struct _PluginState ClutterActor *desktop1; ClutterActor *desktop2; + MutterPluginInfo info; + gboolean debug_mode : 1; -} PluginState; +}; + +static void +mutter_default_plugin_dispose (GObject *object) +{ + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv; + + g_object_unref (priv->destroy_effect); + g_object_unref (priv->minimize_effect); + g_object_unref (priv->maximize_effect); + g_object_unref (priv->switch_workspace_effect); + + G_OBJECT_CLASS (mutter_default_plugin_parent_class)->dispose (object); +} + +static void +mutter_default_plugin_finalize (GObject *object) +{ + G_OBJECT_CLASS (mutter_default_plugin_parent_class)->finalize (object); +} + +static void +mutter_default_plugin_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mutter_default_plugin_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mutter_default_plugin_constructed (GObject *object) +{ + MutterPlugin *plugin = MUTTER_PLUGIN (object); + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv; + + guint destroy_timeout = DESTROY_TIMEOUT; + guint minimize_timeout = MINIMIZE_TIMEOUT; + guint maximize_timeout = MAXIMIZE_TIMEOUT; + guint map_timeout = MAP_TIMEOUT; + guint switch_timeout = SWITCH_TIMEOUT; + + if (mutter_plugin_debug_mode (plugin)) + { + g_debug ("Plugin %s: Entering debug mode.", priv->info.name); + + priv->debug_mode = TRUE; + + /* + * Double the effect duration to make them easier to observe. + */ + destroy_timeout *= 2; + minimize_timeout *= 2; + maximize_timeout *= 2; + map_timeout *= 2; + switch_timeout *= 2; + } + + priv->destroy_effect + = clutter_effect_template_new (clutter_timeline_new_for_duration ( + destroy_timeout), + CLUTTER_ALPHA_SINE_INC); + + + priv->minimize_effect + = clutter_effect_template_new (clutter_timeline_new_for_duration ( + minimize_timeout), + CLUTTER_ALPHA_SINE_INC); + + priv->maximize_effect + = clutter_effect_template_new (clutter_timeline_new_for_duration ( + maximize_timeout), + CLUTTER_ALPHA_SINE_INC); + + priv->map_effect + = clutter_effect_template_new (clutter_timeline_new_for_duration ( + map_timeout), + CLUTTER_ALPHA_SINE_INC); + + priv->switch_workspace_effect + = clutter_effect_template_new (clutter_timeline_new_for_duration ( + switch_timeout), + CLUTTER_ALPHA_SINE_INC); +} + +static void +mutter_default_plugin_class_init (MutterDefaultPluginClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass); + + gobject_class->finalize = mutter_default_plugin_finalize; + gobject_class->dispose = mutter_default_plugin_dispose; + gobject_class->constructed = mutter_default_plugin_constructed; + gobject_class->set_property = mutter_default_plugin_set_property; + gobject_class->get_property = mutter_default_plugin_get_property; + + plugin_class->map = map; + plugin_class->minimize = minimize; + plugin_class->maximize = maximize; + plugin_class->unmaximize = unmaximize; + plugin_class->destroy = destroy; + plugin_class->switch_workspace = switch_workspace; + plugin_class->kill_effect = kill_effect; + plugin_class->plugin_info = plugin_info; + + g_type_class_add_private (gobject_class, sizeof (MutterDefaultPluginPrivate)); +} + +static void +mutter_default_plugin_init (MutterDefaultPlugin *self) +{ + MutterDefaultPluginPrivate *priv; + + self->priv = priv = MUTTER_DEFAULT_PLUGIN_GET_PRIVATE (self); + + priv->info.name = "Default Effects"; + priv->info.version = "0.1"; + priv->info.author = "Intel Corp."; + priv->info.license = "GPL"; + priv->info.description = "This is an example of a plugin implementation."; +} /* @@ -102,8 +271,6 @@ typedef struct _ActorPrivate gboolean is_maximized : 1; } ActorPrivate; -static PluginState *plugin_state; - /* * Actor private data accessor */ @@ -134,53 +301,72 @@ get_actor_private (MutterWindow *actor) return priv; } +typedef struct SwitchWorkspaceData +{ + MutterPlugin *plugin; + const GList **actors; +} SwitchWorkspaceData; + static void on_switch_workspace_effect_complete (ClutterActor *group, gpointer data) { - PluginState *state = plugin_state; - GList *l = *((GList**)data); + SwitchWorkspaceData *sw_data = data; + MutterPlugin *plugin = sw_data->plugin; + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; + GList *l = *((GList**)sw_data->actors); MutterWindow *actor_for_cb = l->data; while (l) { ClutterActor *a = l->data; MutterWindow *mc_window = MUTTER_WINDOW (a); - ActorPrivate *priv = get_actor_private (mc_window); + ActorPrivate *apriv = get_actor_private (mc_window); - if (priv->orig_parent) + if (apriv->orig_parent) { - clutter_actor_reparent (a, priv->orig_parent); - priv->orig_parent = NULL; + clutter_actor_reparent (a, apriv->orig_parent); + apriv->orig_parent = NULL; } l = l->next; } - clutter_actor_destroy (state->desktop1); - clutter_actor_destroy (state->desktop2); + clutter_actor_destroy (priv->desktop1); + clutter_actor_destroy (priv->desktop2); - state->actors = NULL; - state->tml_switch_workspace1 = NULL; - state->tml_switch_workspace2 = NULL; - state->desktop1 = NULL; - state->desktop2 = NULL; + priv->actors = NULL; + priv->tml_switch_workspace1 = NULL; + priv->tml_switch_workspace2 = NULL; + priv->desktop1 = NULL; + priv->desktop2 = NULL; - mutter_plugin_effect_completed (mutter_get_plugin(), actor_for_cb, + g_free (data); + + mutter_plugin_effect_completed (plugin, actor_for_cb, MUTTER_PLUGIN_SWITCH_WORKSPACE); } static void -switch_workspace (const GList **actors, gint from, gint to, +switch_workspace (MutterPlugin *plugin, + const GList **actors, gint from, gint to, MetaMotionDirection direction) { - MutterPlugin *plugin = mutter_get_plugin(); - PluginState *state = plugin_state; + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; GList *l; gint n_workspaces; ClutterActor *workspace0 = clutter_group_new (); ClutterActor *workspace1 = clutter_group_new (); ClutterActor *stage; int screen_width, screen_height; + MetaScreen *screen = mutter_plugin_get_screen (plugin); + SwitchWorkspaceData *sw_data = g_new (SwitchWorkspaceData, 1); + + /* Must chain up first */ + MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)-> + switch_workspace (plugin, actors, from, to, direction); + + sw_data->plugin = plugin; + sw_data->actors = actors; stage = mutter_plugin_get_stage (plugin); @@ -201,19 +387,19 @@ switch_workspace (const GList **actors, gint from, gint to, if (from == to) { - mutter_plugin_effect_completed (mutter_get_plugin(), NULL, + mutter_plugin_effect_completed (plugin, NULL, MUTTER_PLUGIN_SWITCH_WORKSPACE); return; } - n_workspaces = g_list_length (plugin->work_areas); + n_workspaces = meta_screen_get_n_workspaces (screen); l = g_list_last (*((GList**) actors)); while (l) { MutterWindow *mc_window = l->data; - ActorPrivate *priv = get_actor_private (mc_window); + ActorPrivate *apriv = get_actor_private (mc_window); ClutterActor *window = CLUTTER_ACTOR (mc_window); gint win_workspace; @@ -227,7 +413,7 @@ switch_workspace (const GList **actors, gint from, gint to, clutter_actor_get_position (window, &x, &y); clutter_actor_get_size (window, &w, &h); - priv->orig_parent = clutter_actor_get_parent (window); + apriv->orig_parent = clutter_actor_get_parent (window); clutter_actor_reparent (window, win_workspace == to ? workspace1 : workspace0); @@ -237,30 +423,30 @@ switch_workspace (const GList **actors, gint from, gint to, else if (win_workspace < 0) { /* Sticky window */ - priv->orig_parent = NULL; + apriv->orig_parent = NULL; } else { /* Window on some other desktop */ clutter_actor_hide (window); - priv->orig_parent = NULL; + apriv->orig_parent = NULL; } l = l->prev; } - state->actors = (GList **)actors; - state->desktop1 = workspace0; - state->desktop2 = workspace1; + priv->actors = (GList **)actors; + priv->desktop1 = workspace0; + priv->desktop2 = workspace1; - state->tml_switch_workspace2 = - clutter_effect_scale (state->switch_workspace_effect, + priv->tml_switch_workspace2 = + clutter_effect_scale (priv->switch_workspace_effect, workspace1, 1.0, 1.0, on_switch_workspace_effect_complete, - (gpointer)actors); + (gpointer)sw_data); - state->tml_switch_workspace1 = - clutter_effect_scale (state->switch_workspace_effect, + priv->tml_switch_workspace1 = + clutter_effect_scale (priv->switch_workspace_effect, workspace0, 0.0, 0.0, NULL, NULL); } @@ -277,6 +463,7 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data) * Must reverse the effect of the effect; must hide it first to ensure * that the restoration will not be visible. */ + MutterPlugin *plugin = data; ActorPrivate *apriv; MutterWindow *mc_window = MUTTER_WINDOW (actor); @@ -292,7 +479,7 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data) CLUTTER_GRAVITY_NORTH_WEST); /* Now notify the manager that we are done with this effect */ - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MINIMIZE); } @@ -301,11 +488,15 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data) * completion). */ static void -minimize (MutterWindow *mc_window) +minimize (MutterPlugin *plugin, MutterWindow *mc_window) { - PluginState *state = plugin_state; - MetaCompWindowType type; - ClutterActor *actor = CLUTTER_ACTOR (mc_window); + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; + MetaCompWindowType type; + ClutterActor *actor = CLUTTER_ACTOR (mc_window); + + /* Must chain up first */ + MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)-> + minimize (plugin, mc_window); type = mutter_window_get_window_type (mc_window); @@ -318,16 +509,16 @@ minimize (MutterWindow *mc_window) clutter_actor_move_anchor_point_from_gravity (actor, CLUTTER_GRAVITY_CENTER); - apriv->tml_minimize = clutter_effect_scale (state->minimize_effect, + apriv->tml_minimize = clutter_effect_scale (priv->minimize_effect, actor, 0.0, 0.0, (ClutterEffectCompleteFunc) on_minimize_effect_complete, - NULL); + plugin); } else - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MINIMIZE); } @@ -341,6 +532,7 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data) /* * Must reverse the effect of the effect. */ + MutterPlugin * plugin = data; MutterWindow *mc_window = MUTTER_WINDOW (actor); ActorPrivate *apriv = get_actor_private (mc_window); @@ -352,7 +544,7 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data) CLUTTER_GRAVITY_NORTH_WEST); /* Now notify the manager that we are done with this effect */ - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAXIMIZE); } @@ -365,9 +557,11 @@ on_maximize_effect_complete (ClutterActor *actor, gpointer data) * (Something like a sound would be more appropriate.) */ static void -maximize (MutterWindow *mc_window, +maximize (MutterPlugin *plugin, + MutterWindow *mc_window, gint end_x, gint end_y, gint end_width, gint end_height) { + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; MetaCompWindowType type; ClutterActor *actor = CLUTTER_ACTOR (mc_window); @@ -376,6 +570,10 @@ maximize (MutterWindow *mc_window, gint anchor_x = 0; gint anchor_y = 0; + /* Must chain up first */ + MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)-> + maximize (plugin, mc_window, end_x, end_y, end_width, end_height); + type = mutter_window_get_window_type (mc_window); if (type == META_COMP_WINDOW_NORMAL) @@ -404,18 +602,18 @@ maximize (MutterWindow *mc_window, clutter_actor_move_anchor_point (actor, anchor_x, anchor_y); apriv->tml_maximize = - clutter_effect_scale (plugin_state->maximize_effect, + clutter_effect_scale (priv->maximize_effect, actor, scale_x, scale_y, (ClutterEffectCompleteFunc) on_maximize_effect_complete, - NULL); + plugin); return; } - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAXIMIZE); } @@ -425,11 +623,16 @@ maximize (MutterWindow *mc_window, * (Just a skeleton code.) */ static void -unmaximize (MutterWindow *mc_window, +unmaximize (MutterPlugin *plugin, + MutterWindow *mc_window, gint end_x, gint end_y, gint end_width, gint end_height) { MetaCompWindowType type = mutter_window_get_window_type (mc_window); + /* Must chain up first */ + MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)-> + unmaximize (plugin, mc_window, end_x, end_y, end_width, end_height); + if (type == META_COMP_WINDOW_NORMAL) { ActorPrivate *apriv = get_actor_private (mc_window); @@ -438,7 +641,7 @@ unmaximize (MutterWindow *mc_window, } /* Do this conditionally, if the effect requires completion callback. */ - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_UNMAXIMIZE); } @@ -448,6 +651,7 @@ on_map_effect_complete (ClutterActor *actor, gpointer data) /* * Must reverse the effect of the effect. */ + MutterPlugin *plugin = data; MutterWindow *mc_window = MUTTER_WINDOW (actor); ActorPrivate *apriv = get_actor_private (mc_window); @@ -457,7 +661,7 @@ on_map_effect_complete (ClutterActor *actor, gpointer data) CLUTTER_GRAVITY_NORTH_WEST); /* Now notify the manager that we are done with this effect */ - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, MUTTER_PLUGIN_MAP); + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAP); } /* @@ -465,11 +669,16 @@ on_map_effect_complete (ClutterActor *actor, gpointer data) * completion). */ static void -map (MutterWindow *mc_window) +map (MutterPlugin *plugin, MutterWindow *mc_window) { + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; MetaCompWindowType type; ClutterActor *actor = CLUTTER_ACTOR (mc_window); + /* Must chain up first */ + MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)-> + map (plugin, mc_window); + type = mutter_window_get_window_type (mc_window); if (type == META_COMP_WINDOW_NORMAL) @@ -482,19 +691,19 @@ map (MutterWindow *mc_window) clutter_actor_set_scale (actor, 0.0, 0.0); clutter_actor_show (actor); - apriv->tml_map = clutter_effect_scale (plugin_state->map_effect, + apriv->tml_map = clutter_effect_scale (priv->map_effect, actor, 1.0, 1.0, (ClutterEffectCompleteFunc) on_map_effect_complete, - NULL); + plugin); apriv->is_minimized = FALSE; } else - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAP); } @@ -505,7 +714,7 @@ map (MutterWindow *mc_window) static void on_destroy_effect_complete (ClutterActor *actor, gpointer data) { - MutterPlugin *plugin = mutter_get_plugin(); + MutterPlugin *plugin = data; MutterWindow *mc_window = MUTTER_WINDOW (actor); ActorPrivate *apriv = get_actor_private (mc_window); @@ -519,11 +728,16 @@ on_destroy_effect_complete (ClutterActor *actor, gpointer data) * Simple TV-out like effect. */ static void -destroy (MutterWindow *mc_window) +destroy (MutterPlugin *plugin, MutterWindow *mc_window) { + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; MetaCompWindowType type; ClutterActor *actor = CLUTTER_ACTOR (mc_window); + /* Must chain up first */ + MUTTER_PLUGIN_CLASS (mutter_default_plugin_parent_class)-> + destroy (plugin, mc_window); + type = mutter_window_get_window_type (mc_window); if (type == META_COMP_WINDOW_NORMAL) @@ -533,34 +747,34 @@ destroy (MutterWindow *mc_window) clutter_actor_move_anchor_point_from_gravity (actor, CLUTTER_GRAVITY_CENTER); - apriv->tml_destroy = clutter_effect_scale (plugin_state->destroy_effect, + apriv->tml_destroy = clutter_effect_scale (priv->destroy_effect, actor, 1.0, 0.0, (ClutterEffectCompleteFunc) on_destroy_effect_complete, - NULL); + plugin); } else - mutter_plugin_effect_completed (mutter_get_plugin(), mc_window, + mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_DESTROY); } static void -kill_effect (MutterWindow *mc_window, gulong event) +kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event) { ActorPrivate *apriv; ClutterActor *actor = CLUTTER_ACTOR (mc_window); if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE) { - PluginState *state = plugin_state; + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; - if (state->tml_switch_workspace1) + if (priv->tml_switch_workspace1) { - clutter_timeline_stop (state->tml_switch_workspace1); - clutter_timeline_stop (state->tml_switch_workspace2); - on_switch_workspace_effect_complete (state->desktop1, state->actors); + clutter_timeline_stop (priv->tml_switch_workspace1); + clutter_timeline_stop (priv->tml_switch_workspace2); + on_switch_workspace_effect_complete (priv->desktop1, priv->actors); } if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE)) @@ -597,144 +811,10 @@ kill_effect (MutterWindow *mc_window, gulong event) } } - -const gchar * g_module_check_init (GModule *module); -const gchar * -g_module_check_init (GModule *module) +static const MutterPluginInfo * +plugin_info (MutterPlugin *plugin) { - MutterPlugin *plugin = mutter_get_plugin (); + MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; - /* Human readable name (for use in UI) */ - plugin->name = "Default Effects"; - - /* Plugin load time initialiser */ - plugin->do_init = do_init; - - /* Effect handlers */ - plugin->minimize = minimize; - plugin->destroy = destroy; - plugin->map = map; - plugin->maximize = maximize; - plugin->unmaximize = unmaximize; - plugin->switch_workspace = switch_workspace; - plugin->kill_effect = kill_effect; - - /* The reload handler */ - plugin->reload = reload; - - return NULL; + return &priv->info; } - -/* - * Core of the plugin init function, called for initial initialization and - * by the reload() function. Returns TRUE on success. - */ -static gboolean -do_init (const char *params) -{ - guint destroy_timeout = DESTROY_TIMEOUT; - guint minimize_timeout = MINIMIZE_TIMEOUT; - guint maximize_timeout = MAXIMIZE_TIMEOUT; - guint map_timeout = MAP_TIMEOUT; - guint switch_timeout = SWITCH_TIMEOUT; - - plugin_state = g_new0 (PluginState, 1); - - if (params) - { - if (strstr (params, "debug")) - { - g_debug ("%s: Entering debug mode.", mutter_get_plugin()->name); - - plugin_state->debug_mode = TRUE; - - /* - * Double the effect duration to make them easier to observe. - */ - destroy_timeout *= 2; - minimize_timeout *= 2; - maximize_timeout *= 2; - map_timeout *= 2; - switch_timeout *= 2; - } - } - - plugin_state->destroy_effect - = clutter_effect_template_new (clutter_timeline_new_for_duration ( - destroy_timeout), - CLUTTER_ALPHA_SINE_INC); - - - plugin_state->minimize_effect - = clutter_effect_template_new (clutter_timeline_new_for_duration ( - minimize_timeout), - CLUTTER_ALPHA_SINE_INC); - - plugin_state->maximize_effect - = clutter_effect_template_new (clutter_timeline_new_for_duration ( - maximize_timeout), - CLUTTER_ALPHA_SINE_INC); - - plugin_state->map_effect - = clutter_effect_template_new (clutter_timeline_new_for_duration ( - map_timeout), - CLUTTER_ALPHA_SINE_INC); - - plugin_state->switch_workspace_effect - = clutter_effect_template_new (clutter_timeline_new_for_duration ( - switch_timeout), - CLUTTER_ALPHA_SINE_INC); - - return TRUE; -} - -static void -free_plugin_private (PluginState *state) -{ - if (!state) - return; - - g_object_unref (state->destroy_effect); - g_object_unref (state->minimize_effect); - g_object_unref (state->maximize_effect); - g_object_unref (state->switch_workspace_effect); - - g_free (state); -} - -/* - * Called by the plugin manager when we stuff like the command line parameters - * changed. - */ -static gboolean -reload (const char *params) -{ - PluginState *state; - - state = plugin_state; - - if (do_init (params)) - { - /* Success; free the old state */ - free_plugin_private (plugin_state); - return TRUE; - } - else - { - /* Fail -- fall back to the old state. */ - plugin_state = state; - } - - return FALSE; -} - -/* - * GModule unload function -- do any cleanup required. - */ -G_MODULE_EXPORT void g_module_unload (GModule *module); -G_MODULE_EXPORT void -g_module_unload (GModule *module) -{ - free_plugin_private (plugin_state); -} - diff --git a/src/core/display-private.h b/src/core/display-private.h index 4f594285c..1f86e3bb4 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -74,6 +74,8 @@ typedef void (* MetaWindowPingFunc) (MetaDisplay *display, struct _MetaDisplay { + GObject parent_instance; + char *name; Display *xdisplay; @@ -296,6 +298,11 @@ struct _MetaDisplay #endif }; +struct _MetaDisplayClass +{ + GObjectClass parent_class; +}; + /* Xserver time can wraparound, thus comparing two timestamps needs to take * this into account. Here's a little macro to help out. If no wraparound * has occurred, this is equivalent to diff --git a/src/core/display.c b/src/core/display.c index aa6ffc875..b4afa3916 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -127,6 +127,8 @@ typedef struct Window xwindow; } MetaAutoRaiseData; +G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT); + /** * The display we're managing. This is a singleton object. (Historically, * this was a list of displays, but there was never any way to add more @@ -163,6 +165,12 @@ static void sanity_check_timestamps (MetaDisplay *display, MetaGroup* get_focussed_group (MetaDisplay *display); +static void +meta_display_class_init (MetaDisplayClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); +} + /** * Destructor for MetaPingData structs. Will destroy the * event source for the struct as well. @@ -298,6 +306,13 @@ disable_compositor (MetaDisplay *display) display->compositor = NULL; } +static void +meta_display_init (MetaDisplay *disp) +{ + /* Some stuff could go in here that's currently in _open, + * but it doesn't really matter. */ +} + /** * Opens a new display, sets it up, initialises all the X extensions * we will need, and adds it to the list of displays. @@ -340,7 +355,7 @@ meta_display_open (void) XSynchronize (xdisplay, True); g_assert (the_display == NULL); - the_display = g_new (MetaDisplay, 1); + the_display = g_object_new (META_TYPE_DISPLAY, NULL); the_display->closing = 0; @@ -903,7 +918,7 @@ meta_display_close (MetaDisplay *display, } #endif - /* Must be after all calls to meta_window_free() since they + /* Must be after all calls to meta_window_unmanage() since they * unregister windows */ g_hash_table_destroy (display->window_ids); @@ -1992,7 +2007,7 @@ event_callback (XEvent *event, else { /* Unmanage destroyed window */ - meta_window_free (window, timestamp); + meta_window_unmanage (window, timestamp); window = NULL; } } @@ -2025,7 +2040,7 @@ event_callback (XEvent *event, /* Unmanage withdrawn window */ window->withdrawn = TRUE; - meta_window_free (window, timestamp); + meta_window_unmanage (window, timestamp); window = NULL; } else @@ -4828,7 +4843,7 @@ meta_display_unmanage_windows_for_screen (MetaDisplay *display, tmp = winlist; while (tmp != NULL) { - meta_window_free (tmp->data, timestamp); + meta_window_unmanage (tmp->data, timestamp); tmp = tmp->next; } diff --git a/src/core/screen-private.h b/src/core/screen-private.h index e928b612a..246d76e1b 100644 --- a/src/core/screen-private.h +++ b/src/core/screen-private.h @@ -69,6 +69,8 @@ typedef enum struct _MetaScreen { + GObject parent_instance; + MetaDisplay *display; int number; char *screen_name; @@ -139,6 +141,11 @@ struct _MetaScreen Window guard_window; }; +struct _MetaScreenClass +{ + GObjectClass parent_class; +}; + MetaScreen* meta_screen_new (MetaDisplay *display, int number, guint32 timestamp); diff --git a/src/core/screen.c b/src/core/screen.c index 2d8c1a89a..9d3c43d03 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -69,6 +69,82 @@ static void meta_screen_sn_event (SnMonitorEvent *event, void *user_data); #endif +enum +{ + PROP_N_WORKSPACES = 1 +}; + +G_DEFINE_TYPE (MetaScreen, meta_screen, G_TYPE_OBJECT); + +static void +meta_screen_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ +#if 0 + MetaScreen *screen = META_SCREEN (object); +#endif + + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +meta_screen_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MetaScreen *screen = META_SCREEN (object); + + switch (prop_id) + { + case PROP_N_WORKSPACES: + g_value_set_int (value, meta_screen_get_n_workspaces (screen)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +meta_screen_finalize (GObject *object) +{ + /* Actual freeing done in meta_screen_free() for now */ +} + +static void +meta_screen_class_init (MetaScreenClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + object_class->get_property = meta_screen_get_property; + object_class->set_property = meta_screen_set_property; + object_class->finalize = meta_screen_finalize; + + pspec = g_param_spec_int ("n-workspaces", + "N Workspaces", + "Number of workspaces", + 1, G_MAXINT, 1, + G_PARAM_READABLE); + + g_object_class_install_property (object_class, + PROP_N_WORKSPACES, + pspec); +} + +static void +meta_screen_init (MetaScreen *screen) +{ +} + static int set_wm_check_hint (MetaScreen *screen) { @@ -488,7 +564,7 @@ meta_screen_new (MetaDisplay *display, return NULL; } - screen = g_new (MetaScreen, 1); + screen = g_object_new (META_TYPE_SCREEN, NULL); screen->closing = 0; screen->display = display; @@ -718,7 +794,8 @@ meta_screen_free (MetaScreen *screen, g_free (screen->xinerama_infos); g_free (screen->screen_name); - g_free (screen); + + g_object_unref (screen); XFlush (display->xdisplay); meta_display_ungrab (display); @@ -1110,11 +1187,13 @@ meta_screen_remove_workspace (MetaScreen *screen, MetaWorkspace *workspace, meta_workspace_activate (neighbour, timestamp); /* This also removes the workspace from the screens list */ - meta_workspace_free (workspace); + meta_workspace_remove (workspace); set_number_of_spaces_hint (screen, g_list_length (screen->workspaces)); meta_screen_queue_workarea_recalc (screen); + + g_object_notify (G_OBJECT (screen), "n-workspaces"); } MetaWorkspace * @@ -1136,6 +1215,8 @@ meta_screen_append_new_workspace (MetaScreen *screen, gboolean activate, meta_screen_queue_workarea_recalc (screen); + g_object_notify (G_OBJECT (screen), "n-workspaces"); + return w; } @@ -1204,7 +1285,7 @@ update_num_workspaces (MetaScreen *screen, MetaWorkspace *w = tmp->data; g_assert (w->windows == NULL); - meta_workspace_free (w); + meta_workspace_remove (w); tmp = tmp->next; } @@ -1220,6 +1301,8 @@ update_num_workspaces (MetaScreen *screen, set_number_of_spaces_hint (screen, new_num); meta_screen_queue_workarea_recalc (screen); + + g_object_notify (G_OBJECT (screen), "n-workspaces"); } static void diff --git a/src/core/window-private.h b/src/core/window-private.h index 6a555d090..7afc8c8d1 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -66,6 +66,8 @@ typedef enum { struct _MetaWindow { + GObject parent_instance; + MetaDisplay *display; MetaScreen *screen; MetaWorkspace *workspace; @@ -242,7 +244,7 @@ struct _MetaWindow /* Has this window not ever been shown yet? */ guint showing_for_first_time : 1; - /* Are we in meta_window_free()? */ + /* Are we in meta_window_unmanage()? */ guint unmanaging : 1; /* Are we in meta_window_new()? */ @@ -363,6 +365,11 @@ struct _MetaWindow #endif }; +struct _MetaWindowClass +{ + GObjectClass parent_class; +}; + /* These differ from window->has_foo_func in that they consider * the dynamic window state such as "maximized", not just the * window's type @@ -386,7 +393,7 @@ MetaWindow* meta_window_new_with_attrs (MetaDisplay *display, Window xwindow, gboolean must_be_viewable, XWindowAttributes *attrs); -void meta_window_free (MetaWindow *window, +void meta_window_unmanage (MetaWindow *window, guint32 timestamp); void meta_window_calc_showing (MetaWindow *window); void meta_window_queue (MetaWindow *window, diff --git a/src/core/window-props.c b/src/core/window-props.c index 59feadf75..602d29561 100644 --- a/src/core/window-props.c +++ b/src/core/window-props.c @@ -384,6 +384,8 @@ set_window_title (MetaWindow *window, meta_ui_set_frame_title (window->screen->ui, window->frame->xwindow, window->title); + if (modified) + g_object_notify (G_OBJECT (window), "title"); } static void diff --git a/src/core/window.c b/src/core/window.c index 42a92361f..3b175607d 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -2,12 +2,12 @@ /* Metacity X managed windows */ -/* +/* * Copyright (C) 2001 Havoc Pennington, Anders Carlsson * Copyright (C) 2002, 2003 Red Hat, Inc. * Copyright (C) 2003 Rob Adams * Copyright (C) 2004-2006 Elijah Newren - * + * * 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 @@ -17,7 +17,7 @@ * 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 @@ -132,6 +132,118 @@ static gboolean idle_calc_showing (gpointer data); static gboolean idle_move_resize (gpointer data); static gboolean idle_update_icon (gpointer data); +G_DEFINE_TYPE (MetaWindow, meta_window, G_TYPE_OBJECT); + +enum { + PROP_0, + + PROP_TITLE, + PROP_ICON, + PROP_MINI_ICON, +}; + +static void +meta_window_finalize (GObject *object) +{ + MetaWindow *window = META_WINDOW (object); + + if (window->icon) + g_object_unref (G_OBJECT (window->icon)); + + if (window->mini_icon) + g_object_unref (G_OBJECT (window->mini_icon)); + + meta_icon_cache_free (&window->icon_cache); + + g_free (window->sm_client_id); + g_free (window->wm_client_machine); + g_free (window->startup_id); + g_free (window->role); + g_free (window->res_class); + g_free (window->res_name); + g_free (window->title); + g_free (window->icon_name); + g_free (window->desc); +} + +static void +meta_window_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MetaWindow *win = META_WINDOW (object); + + switch (prop_id) + { + case PROP_TITLE: + g_value_set_string (value, win->title); + break; + case PROP_ICON: + g_value_set_object (value, win->icon); + break; + case PROP_MINI_ICON: + g_value_set_object (value, win->mini_icon); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +meta_window_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +meta_window_class_init (MetaWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_window_finalize; + + object_class->get_property = meta_window_get_property; + object_class->set_property = meta_window_set_property; + + g_object_class_install_property (object_class, + PROP_TITLE, + g_param_spec_string ("title", + "Title", + "The title of the window", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_ICON, + g_param_spec_object ("icon", + "Icon", + "32 pixel sized icon", + GDK_TYPE_PIXBUF, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_MINI_ICON, + g_param_spec_object ("mini-icon", + "Mini Icon", + "16 pixel sized icon", + GDK_TYPE_PIXBUF, + G_PARAM_READABLE)); +} + +static void +meta_window_init (MetaWindow *self) +{ +} + #ifdef WITH_VERBOSE_MODE static const char* wm_state_to_string (int state) @@ -139,7 +251,7 @@ wm_state_to_string (int state) switch (state) { case NormalState: - return "NormalState"; + return "NormalState"; case IconicState: return "IconicState"; case WithdrawnState: @@ -192,7 +304,7 @@ maybe_leave_show_desktop_mode (MetaWindow *window) { meta_screen_minimize_all_on_active_workspace_except (window->screen, window); - meta_screen_unshow_desktop (window->screen); + meta_screen_unshow_desktop (window->screen); } } @@ -203,15 +315,15 @@ meta_window_new (MetaDisplay *display, { XWindowAttributes attrs; MetaWindow *window; - + meta_display_grab (display); meta_error_trap_push (display); /* Push a trap over all of window * creation, to reduce XSync() calls */ - + meta_error_trap_push_with_return (display); - - if (XGetWindowAttributes (display->xdisplay,xwindow, &attrs)) + + if (XGetWindowAttributes (display->xdisplay,xwindow, &attrs)) { if(meta_error_trap_pop_with_return (display, TRUE) != Success) { @@ -226,15 +338,15 @@ meta_window_new (MetaDisplay *display, } else { - meta_error_trap_pop_with_return (display, TRUE); + meta_error_trap_pop_with_return (display, TRUE); meta_verbose ("Failed to get attributes for window 0x%lx\n", xwindow); meta_error_trap_pop (display, TRUE); meta_display_ungrab (display); return NULL; } - - + + meta_error_trap_pop (display, FALSE); meta_display_ungrab (display); @@ -261,7 +373,7 @@ meta_window_new_with_attrs (MetaDisplay *display, g_assert (attrs != NULL); g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props)); - + meta_verbose ("Attempting to manage 0x%lx\n", xwindow); if (meta_display_xwindow_is_a_no_focus_window (display, xwindow)) @@ -282,9 +394,9 @@ meta_window_new_with_attrs (MetaDisplay *display, break; } } - + g_assert (screen); - + /* A black list of override redirect windows that we don't need to manage: */ if (attrs->override_redirect && (xwindow == screen->no_focus_window || @@ -324,7 +436,7 @@ meta_window_new_with_attrs (MetaDisplay *display, (attrs->map_state == IsUnviewable) ? "IsUnviewable" : "(unknown)"); - + existing_wm_state = WithdrawnState; if (must_be_viewable && attrs->map_state != IsViewable) { @@ -348,9 +460,9 @@ meta_window_new_with_attrs (MetaDisplay *display, meta_verbose ("WM_STATE of %lx = %s\n", xwindow, wm_state_to_string (existing_wm_state)); } - + meta_error_trap_push_with_return (display); - + /* * XAddToSaveSet can only be called on windows created by a different client. * with Mutter we want to be able to create manageable windows from within @@ -404,15 +516,15 @@ meta_window_new_with_attrs (MetaDisplay *display, if (attrs->win_gravity != NorthWestGravity) { XSetWindowAttributes set_attrs; - + set_attrs.win_gravity = NorthWestGravity; - + XChangeWindowAttributes (display->xdisplay, xwindow, CWWinGravity, &set_attrs); } - + if (meta_error_trap_pop_with_return (display, FALSE) != Success) { meta_verbose ("Window 0x%lx disappeared just as we tried to manage it\n", @@ -422,15 +534,16 @@ meta_window_new_with_attrs (MetaDisplay *display, return NULL; } - window = g_new (MetaWindow, 1); + + window = g_object_new (META_TYPE_WINDOW, NULL); window->constructing = TRUE; - + window->dialog_pid = -1; window->dialog_pipe = -1; - + window->xwindow = xwindow; - + /* this is in window->screen->display, but that's too annoying to * type */ @@ -443,7 +556,7 @@ meta_window_new_with_attrs (MetaDisplay *display, window->sync_request_time.tv_sec = 0; window->sync_request_time.tv_usec = 0; #endif - + window->screen = screen; window->desc = g_strdup_printf ("0x%lx", window->xwindow); @@ -454,7 +567,7 @@ meta_window_new_with_attrs (MetaDisplay *display, meta_stack_freeze (window->screen->stack); window->has_shape = has_shape; - + window->rect.x = attrs->x; window->rect.y = attrs->y; window->rect.width = attrs->width; @@ -472,11 +585,11 @@ meta_window_new_with_attrs (MetaDisplay *display, /* And this is our unmaximized size */ window->saved_rect = window->rect; window->user_rect = window->rect; - + window->depth = attrs->depth; window->xvisual = attrs->visual; window->colormap = attrs->colormap; - + window->title = NULL; window->icon_name = NULL; window->icon = NULL; @@ -530,9 +643,9 @@ meta_window_new_with_attrs (MetaDisplay *display, window->shaken_loose = FALSE; window->have_focus_click_grab = FALSE; window->disable_sync = FALSE; - + window->unmaps_pending = 0; - + window->mwm_decorated = TRUE; window->mwm_border_only = FALSE; window->mwm_has_close_func = TRUE; @@ -540,7 +653,7 @@ meta_window_new_with_attrs (MetaDisplay *display, window->mwm_has_maximize_func = TRUE; window->mwm_has_move_func = TRUE; window->mwm_has_resize_func = TRUE; - + window->decorated = TRUE; window->has_close_func = TRUE; window->has_minimize_func = TRUE; @@ -553,7 +666,7 @@ meta_window_new_with_attrs (MetaDisplay *display, window->has_fullscreen_func = TRUE; window->always_sticky = FALSE; - + window->wm_state_modal = FALSE; window->skip_taskbar = FALSE; window->skip_pager = FALSE; @@ -562,20 +675,20 @@ meta_window_new_with_attrs (MetaDisplay *display, window->wm_state_above = FALSE; window->wm_state_below = FALSE; window->wm_state_demands_attention = FALSE; - + window->res_class = NULL; window->res_name = NULL; window->role = NULL; window->sm_client_id = NULL; window->wm_client_machine = NULL; window->startup_id = NULL; - + window->net_wm_pid = -1; - + window->xtransient_for = None; window->xclient_leader = None; window->transient_parent_is_root_window = FALSE; - + window->type = META_WINDOW_NORMAL; window->type_atom = None; @@ -587,14 +700,14 @@ meta_window_new_with_attrs (MetaDisplay *display, window->using_net_wm_visible_icon_name = FALSE; window->need_reread_icon = TRUE; - + window->layer = META_LAYER_LAST; /* invalid value */ window->stack_position = -1; window->initial_workspace = 0; /* not used */ window->initial_timestamp = 0; /* not used */ window->compositor_private = NULL; - + meta_display_register_x_window (display, &window->xwindow, window); @@ -603,7 +716,7 @@ meta_window_new_with_attrs (MetaDisplay *display, window->group = NULL; window->xgroup_leader = None; meta_window_compute_group (window); - + /* Fill these in the order we want them to be gotten. we want to * get window name and class first so we can use them in error * messages and such. However, name is modified depending on @@ -630,9 +743,9 @@ meta_window_new_with_attrs (MetaDisplay *display, initial_props[i++] = display->atom__NET_WM_USER_TIME_WINDOW; initial_props[i++] = display->atom__NET_WM_FULLSCREEN_MONITORS; g_assert (N_INITIAL_PROPS == i); - + meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS); - + if (!window->override_redirect) update_sm_hints (window); /* must come after transient_for */ update_role (window); @@ -694,7 +807,7 @@ meta_window_new_with_attrs (MetaDisplay *display, window->net_wm_user_time = meta_display_get_current_time_roundtrip (window->display); } - + if (window->decorated) meta_window_ensure_frame (window); @@ -716,12 +829,12 @@ meta_window_new_with_attrs (MetaDisplay *display, */ window->on_all_workspaces = TRUE; } - + /* For the workspace, first honor hints, * if that fails put transients with parents, * otherwise put window on active space */ - + if (window->initial_workspace_set) { if (window->initial_workspace == (int) 0xFFFFFFFF) @@ -729,7 +842,7 @@ meta_window_new_with_attrs (MetaDisplay *display, meta_topic (META_DEBUG_PLACEMENT, "Window %s is initially on all spaces\n", window->desc); - + /* need to set on_all_workspaces first so that it will be * added to all the MRU lists */ @@ -745,13 +858,13 @@ meta_window_new_with_attrs (MetaDisplay *display, space = meta_screen_get_workspace_by_index (window->screen, window->initial_workspace); - + if (space) meta_workspace_add_window (space, window); } } - - if (window->workspace == NULL && + + if (window->workspace == NULL && window->xtransient_for != None) { /* Try putting dialog on parent's workspace */ @@ -765,31 +878,31 @@ meta_window_new_with_attrs (MetaDisplay *display, meta_topic (META_DEBUG_PLACEMENT, "Putting window %s on same workspace as parent %s\n", window->desc, parent->desc); - + if (parent->on_all_workspaces) window->on_all_workspaces = TRUE; - + /* this will implicitly add to the appropriate MRU lists */ meta_workspace_add_window (parent->workspace, window); } } - + if (window->workspace == NULL) { meta_topic (META_DEBUG_PLACEMENT, "Putting window %s on active workspace\n", window->desc); - + space = window->screen->active_workspace; meta_workspace_add_window (space, window); } - + /* for the various on_all_workspaces = TRUE possible above */ if (!window->override_redirect) meta_window_set_current_workspace_hint (window); - + meta_window_update_struts (window); /* Must add window to stack before doing move/resize, since the @@ -799,7 +912,7 @@ meta_window_new_with_attrs (MetaDisplay *display, * and thus constraints may try to auto-fullscreen it which also * means restacking it. */ - meta_stack_add (window->screen->stack, + meta_stack_add (window->screen->stack, window); /* Put our state back where it should be, @@ -828,7 +941,7 @@ meta_window_new_with_attrs (MetaDisplay *display, meta_window_release_saved_state (info); } } - + if (!window->override_redirect) { /* FIXME we have a tendency to set this then immediately @@ -843,7 +956,7 @@ meta_window_new_with_attrs (MetaDisplay *display, /* disable show desktop mode unless we're a desktop component */ maybe_leave_show_desktop_mode (window); - + meta_window_queue (window, META_QUEUE_CALC_SHOWING); /* See bug 303284; a transient of the given window can already exist, in which * case we think it should probably be shown. @@ -866,7 +979,7 @@ meta_window_new_with_attrs (MetaDisplay *display, meta_error_trap_pop (display, FALSE); /* pop the XSync()-reducing trap */ meta_display_ungrab (display); - + window->constructing = FALSE; if (screen->display->compositor) @@ -904,10 +1017,10 @@ meta_window_apply_session_info (MetaWindow *window, meta_topic (META_DEBUG_SM, "Restoring maximized state %d for window %s\n", info->maximized, window->desc); - + if (window->has_maximize_func && info->maximized) { - meta_window_maximize (window, + meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); @@ -920,7 +1033,7 @@ meta_window_apply_session_info (MetaWindow *window, info->saved_rect.width, info->saved_rect.height, window->desc); - + window->saved_rect.x = info->saved_rect.x; window->saved_rect.y = info->saved_rect.y; window->saved_rect.width = info->saved_rect.width; @@ -928,7 +1041,7 @@ meta_window_apply_session_info (MetaWindow *window, } } } - + if (info->on_all_workspaces_set) { window->on_all_workspaces = info->on_all_workspaces; @@ -936,26 +1049,26 @@ meta_window_apply_session_info (MetaWindow *window, "Restoring sticky state %d for window %s\n", window->on_all_workspaces, window->desc); } - + if (info->workspace_indices) { GSList *tmp; - GSList *spaces; + GSList *spaces; spaces = NULL; - + tmp = info->workspace_indices; while (tmp != NULL) { - MetaWorkspace *space; + MetaWorkspace *space; space = meta_screen_get_workspace_by_index (window->screen, GPOINTER_TO_INT (tmp->data)); - + if (space) spaces = g_slist_prepend (spaces, space); - + tmp = tmp->next; } @@ -973,13 +1086,13 @@ meta_window_apply_session_info (MetaWindow *window, * happened to be on more than one, since we have replaces * window->workspaces with window->workspace */ - meta_workspace_add_window (spaces->data, window); + meta_workspace_add_window (spaces->data, window); meta_topic (META_DEBUG_SM, "Restoring saved window %s to workspace %d\n", window->desc, meta_workspace_index (spaces->data)); - + g_slist_free (spaces); } } @@ -988,7 +1101,7 @@ meta_window_apply_session_info (MetaWindow *window, { int x, y, w, h; MetaMoveResizeFlags flags; - + window->placed = TRUE; /* don't do placement algorithms later */ x = info->rect.x; @@ -1001,11 +1114,11 @@ meta_window_apply_session_info (MetaWindow *window, /* Force old gravity, ignoring anything now set */ window->size_hints.win_gravity = info->gravity; - + meta_topic (META_DEBUG_SM, "Restoring pos %d,%d size %d x %d for %s\n", x, y, w, h, window->desc); - + flags = META_DO_GRAVITY_ADJUST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION; meta_window_move_resize_internal (window, flags, @@ -1015,27 +1128,27 @@ meta_window_apply_session_info (MetaWindow *window, } void -meta_window_free (MetaWindow *window, - guint32 timestamp) +meta_window_unmanage (MetaWindow *window, + guint32 timestamp) { GList *tmp; - + meta_verbose ("Unmanaging 0x%lx\n", window->xwindow); if (window->display->compositor) meta_compositor_remove_window (window->display->compositor, window); - + if (window->display->window_with_menu == window) { meta_ui_window_menu_free (window->display->window_menu); window->display->window_menu = NULL; window->display->window_with_menu = NULL; } - + if (destroying_windows_disallowed > 0) meta_bug ("Tried to destroy window %s while destruction was not allowed\n", window->desc); - + window->unmanaging = TRUE; if (window->fullscreen) @@ -1057,7 +1170,7 @@ meta_window_free (MetaWindow *window, * group.c won't re-add to the * group if window->unmanaging */ - + /* If we have the focus, focus some other window. * This is done first, so that if the unmap causes * an EnterNotify the EnterNotify will have final say @@ -1100,12 +1213,12 @@ meta_window_free (MetaWindow *window, window->desc); invalidate_work_areas (window); } - + if (window->display->grab_window == window) meta_display_end_grab_op (window->display, timestamp); g_assert (window->display->grab_window != window); - + if (window->display->focus_window == window) { window->display->focus_window = NULL; @@ -1121,12 +1234,12 @@ meta_window_free (MetaWindow *window, * also do this just in case a window got unmaximized.) */ send_configure_notify (window); - + meta_window_unqueue (window, META_QUEUE_CALC_SHOWING | META_QUEUE_MOVE_RESIZE | META_QUEUE_UPDATE_ICON); meta_window_free_delete_dialog (window); - + if (window->workspace) meta_workspace_remove_window (window->workspace, window); @@ -1144,12 +1257,12 @@ meta_window_free (MetaWindow *window, tmp = tmp->next; } #endif - + meta_stack_remove (window->screen->stack, window); - + if (window->frame) meta_window_destroy_frame (window); - + if (window->withdrawn) { /* We need to clean off the window's state so it @@ -1193,9 +1306,9 @@ meta_window_free (MetaWindow *window, meta_window_ungrab_keys (window); meta_display_ungrab_window_buttons (window->display, window->xwindow); meta_display_ungrab_focus_window_button (window->display, window); - + meta_display_unregister_x_window (window->display, window->xwindow); - + meta_error_trap_push (window->display); @@ -1229,27 +1342,10 @@ meta_window_free (MetaWindow *window, if (META_DISPLAY_HAS_SHAPE (window->display)) XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask); #endif - + meta_error_trap_pop (window->display, FALSE); - if (window->icon) - g_object_unref (G_OBJECT (window->icon)); - - if (window->mini_icon) - g_object_unref (G_OBJECT (window->mini_icon)); - - meta_icon_cache_free (&window->icon_cache); - - g_free (window->sm_client_id); - g_free (window->wm_client_machine); - g_free (window->startup_id); - g_free (window->role); - g_free (window->res_class); - g_free (window->res_name); - g_free (window->title); - g_free (window->icon_name); - g_free (window->desc); - g_free (window); + g_object_unref (window); } static void @@ -1257,10 +1353,10 @@ set_wm_state (MetaWindow *window, int state) { unsigned long data[2]; - + meta_verbose ("Setting wm state %s on %s\n", wm_state_to_string (state), window->desc); - + /* Metacity doesn't use icon windows, so data[1] should be None * according to the ICCCM 2.0 Section 4.1.3.1. */ @@ -1280,7 +1376,7 @@ set_net_wm_state (MetaWindow *window) { int i; unsigned long data[12]; - + i = 0; if (window->shaded) { @@ -1344,7 +1440,7 @@ set_net_wm_state (MetaWindow *window) } meta_verbose ("Setting _NET_WM_STATE with %d atoms\n", i); - + meta_error_trap_push (window->display); XChangeProperty (window->display->xdisplay, window->xwindow, window->display->atom__NET_WM_STATE, @@ -1415,7 +1511,7 @@ meta_window_showing_on_its_workspace (MetaWindow *window) /* 1. See if we're minimized */ if (window->minimized) showing = FALSE; - + /* 2. See if we're in "show desktop" mode */ is_desktop_or_dock = FALSE; is_desktop_or_dock_foreach (window, @@ -1431,7 +1527,7 @@ meta_window_showing_on_its_workspace (MetaWindow *window) else /* This only seems to be needed for startup */ workspace_of_window = NULL; - if (showing && + if (showing && workspace_of_window && workspace_of_window->showing_desktop && !is_desktop_or_dock) { @@ -1444,7 +1540,7 @@ meta_window_showing_on_its_workspace (MetaWindow *window) * ancestor's "mapped" field may not be up to date * since it's being computed in this same idle queue) */ - + if (showing) { if (ancestor_is_minimized (window)) @@ -1455,7 +1551,7 @@ meta_window_showing_on_its_workspace (MetaWindow *window) /* 4. See if we're drawing wireframe */ if (window->display->grab_window == window && - window->display->grab_wireframe_active) + window->display->grab_wireframe_active) showing = FALSE; #endif @@ -1470,7 +1566,7 @@ meta_window_should_be_showing (MetaWindow *window) meta_verbose ("Should be showing for window %s\n", window->desc); /* See if we're on the workspace */ - on_workspace = meta_window_located_on_workspace (window, + on_workspace = meta_window_located_on_workspace (window, window->screen->active_workspace); if (!on_workspace) @@ -1499,12 +1595,12 @@ finish_minimize (gpointer data) * haven't done that yet. */ guint32 timestamp = meta_display_get_current_time_roundtrip (window->display); - + meta_window_hide (window); if (window->has_focus) { meta_workspace_focus_default_window (window->screen->active_workspace, - window, + window, timestamp); } } @@ -1516,14 +1612,14 @@ implement_showing (MetaWindow *window, /* Actually show/hide the window */ meta_verbose ("Implement showing = %d for window %s\n", showing, window->desc); - + if (!showing) { gboolean on_workspace; - on_workspace = meta_window_located_on_workspace (window, + on_workspace = meta_window_located_on_workspace (window, window->screen->active_workspace); - + /* Really this effects code should probably * be in meta_window_hide so the window->mapped * test isn't duplicated here. Anyhow, we animate @@ -1535,15 +1631,15 @@ implement_showing (MetaWindow *window, { MetaRectangle icon_rect, window_rect; gboolean result; - + /* Check if the window has an icon geometry */ result = meta_window_get_icon_geometry (window, &icon_rect); - + if (!result) { /* just animate into the corner somehow - maybe * not a good idea... - */ + */ icon_rect.x = window->screen->rect.width; icon_rect.y = window->screen->rect.height; icon_rect.width = 1; @@ -1625,7 +1721,7 @@ idle_calc_showing (gpointer data) queue_idle[queue_index] = 0; destroying_windows_disallowed += 1; - + /* We map windows from top to bottom and unmap from bottom to * top, to avoid extra expose events. The exception is * for unplaced windows, which have to be mapped from bottom to @@ -1649,7 +1745,7 @@ idle_calc_showing (gpointer data) should_show = g_slist_prepend (should_show, window); else should_hide = g_slist_prepend (should_hide, window); - + tmp = tmp->next; } @@ -1663,7 +1759,7 @@ idle_calc_showing (gpointer data) first_window = copy->data; meta_display_grab (first_window->display); - + tmp = unplaced; while (tmp != NULL) { @@ -1672,7 +1768,7 @@ idle_calc_showing (gpointer data) window = tmp->data; meta_window_calc_showing (window); - + tmp = tmp->next; } @@ -1684,10 +1780,10 @@ idle_calc_showing (gpointer data) window = tmp->data; implement_showing (window, TRUE); - + tmp = tmp->next; } - + tmp = should_hide; while (tmp != NULL) { @@ -1696,10 +1792,10 @@ idle_calc_showing (gpointer data) window = tmp->data; implement_showing (window, FALSE); - + tmp = tmp->next; } - + tmp = copy; while (tmp != NULL) { @@ -1713,7 +1809,7 @@ idle_calc_showing (gpointer data) * we are still in the calc_showing queue */ window->is_in_queues &= ~META_QUEUE_CALC_SHOWING; - + tmp = tmp->next; } @@ -1728,7 +1824,7 @@ idle_calc_showing (gpointer data) while (tmp != NULL) { MetaWindow *window = tmp->data; - + if (!window->display->mouse_mode) meta_display_increment_focus_sentinel (window->display); @@ -1737,16 +1833,16 @@ idle_calc_showing (gpointer data) } meta_display_ungrab (first_window->display); - + g_slist_free (copy); g_slist_free (unplaced); g_slist_free (should_show); g_slist_free (should_hide); g_slist_free (displays); - + destroying_windows_disallowed -= 1; - + return FALSE; } @@ -1772,7 +1868,7 @@ meta_window_unqueue (MetaWindow *window, guint queuebits) /* Note that window may not actually be in the queue * because it may have been in "copy" inside the idle handler - */ + */ queue_pending[queuenum] = g_slist_remove (queue_pending[queuenum], window); window->is_in_queues &= ~(1<desc, - compare, + compare, focus_window->net_wm_user_time); return TRUE; } @@ -2011,7 +2107,7 @@ __window_is_terminal (MetaWindow *window) * and the focus_window have no relation */ static void -window_state_on_map (MetaWindow *window, +window_state_on_map (MetaWindow *window, gboolean *takes_focus, gboolean *places_on_top) { @@ -2110,12 +2206,12 @@ window_would_be_covered (const MetaWindow *newbie) { MetaWorkspace *workspace = newbie->workspace; GList *tmp, *windows; - + windows = meta_workspace_list_windows (workspace); tmp = windows; while (tmp != NULL) - { + { MetaWindow *w = tmp->data; if (w->wm_state_above && w != newbie) @@ -2231,7 +2327,7 @@ meta_window_show (MetaWindow *window) */ window->denied_focus_and_not_transient = FALSE; } - + if (needs_stacking_adjustment) { gboolean overlap; @@ -2245,7 +2341,7 @@ meta_window_show (MetaWindow *window) * Firstly, set the flag so we don't give the window focus anyway * and confuse people. */ - + takes_focus_on_map = FALSE; overlap = windows_overlap (window, focus_window); @@ -2264,7 +2360,7 @@ meta_window_show (MetaWindow *window) * in the stack when it doesn't overlap it confusingly places * that new window below a lot of other windows. */ - if (overlap || + if (overlap || (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK && meta_prefs_get_raise_on_click ())) meta_window_stack_just_below (window, focus_window); @@ -2273,17 +2369,17 @@ meta_window_show (MetaWindow *window) * user might not notice the window appearing so set the * demands attention hint. * - * We set the hint ourselves rather than calling + * We set the hint ourselves rather than calling * meta_window_set_demands_attention() because that would cause * a recalculation of overlap, and a call to set_net_wm_state() * which we are going to call ourselves here a few lines down. */ if (overlap) window->wm_state_demands_attention = TRUE; - } + } /* Shaded means the frame is mapped but the window is not */ - + if (window->frame && !window->frame->mapped) { meta_topic (META_DEBUG_WINDOW_STATE, @@ -2296,7 +2392,7 @@ meta_window_show (MetaWindow *window) if (window->shaded) { if (window->mapped) - { + { meta_topic (META_DEBUG_WINDOW_STATE, "%s actually needs unmap (shaded)\n", window->desc); meta_topic (META_DEBUG_WINDOW_STATE, @@ -2327,7 +2423,7 @@ meta_window_show (MetaWindow *window) meta_error_trap_pop (window->display, FALSE); did_show = TRUE; } - + if (meta_prefs_get_live_hidden_windows ()) { if (window->hidden) @@ -2352,9 +2448,9 @@ meta_window_show (MetaWindow *window) && meta_window_get_icon_geometry (window, &icon_rect)) { MetaRectangle window_rect; - + meta_window_get_outer_rect (window, &window_rect); - + if (window->display->compositor) meta_compositor_unminimize_window (window->display->compositor, window, @@ -2372,7 +2468,7 @@ meta_window_show (MetaWindow *window) window->was_minimized = FALSE; } - + if (window->iconic) { window->iconic = FALSE; @@ -2388,7 +2484,7 @@ meta_window_show (MetaWindow *window) { window->showing_for_first_time = FALSE; if (takes_focus_on_map) - { + { meta_window_focus (window, timestamp); } else @@ -2493,9 +2589,9 @@ meta_window_hide (MetaWindow *window) window->iconic = TRUE; set_wm_state (window, IconicState); } - + set_net_wm_state (window); - + if (did_hide && window->struts) { meta_topic (META_DEBUG_WORKAREA, @@ -2524,7 +2620,7 @@ meta_window_minimize (MetaWindow *window) meta_window_foreach_transient (window, queue_calc_showing_func, NULL); - + if (window->has_focus) { meta_topic (META_DEBUG_FOCUS, @@ -2567,7 +2663,7 @@ ensure_size_hints_satisfied (MetaRectangle *rect, maxw = size_hints->max_width; maxh = size_hints->max_height; basew = size_hints->base_width; baseh = size_hints->base_height; winc = size_hints->width_inc; hinc = size_hints->height_inc; - + /* First, enforce min/max size constraints */ rect->width = CLAMP (rect->width, minw, maxw); rect->height = CLAMP (rect->height, minh, maxh); @@ -2669,15 +2765,15 @@ meta_window_maximize_internal (MetaWindow *window, maximize_horizontally && maximize_vertically ? "" : maximize_horizontally ? " horizontally" : maximize_vertically ? " vertically" : "BUGGGGG"); - + if (saved_rect != NULL) window->saved_rect = *saved_rect; else meta_window_save_rect (window); - - window->maximized_horizontally = + + window->maximized_horizontally = window->maximized_horizontally || maximize_horizontally; - window->maximized_vertically = + window->maximized_vertically = window->maximized_vertically || maximize_vertically; /* Fix for #336850: If the frame shape isn't reapplied, it is @@ -2687,7 +2783,7 @@ meta_window_maximize_internal (MetaWindow *window, */ if (window->frame) window->frame->need_reapply_frame_shape = TRUE; - + recalc_window_features (window); set_net_wm_state (window); } @@ -2713,25 +2809,25 @@ meta_window_maximize (MetaWindow *window, /* Shading sucks anyway; I'm not adding a timestamp argument * to this function just for this niche usage & corner case. */ - guint32 timestamp = + guint32 timestamp = meta_display_get_current_time_roundtrip (window->display); meta_window_unshade (window, timestamp); } - + /* if the window hasn't been placed yet, we'll maximize it then */ if (!window->placed) { - window->maximize_horizontally_after_placement = - window->maximize_horizontally_after_placement || + window->maximize_horizontally_after_placement = + window->maximize_horizontally_after_placement || maximize_horizontally; - window->maximize_vertically_after_placement = - window->maximize_vertically_after_placement || + window->maximize_vertically_after_placement = + window->maximize_vertically_after_placement || maximize_vertically; return; } - meta_window_maximize_internal (window, + meta_window_maximize_internal (window, directions, NULL); @@ -2811,10 +2907,10 @@ meta_window_unmaximize (MetaWindow *window, unmaximize_horizontally && unmaximize_vertically ? "" : unmaximize_horizontally ? " horizontally" : unmaximize_vertically ? " vertically" : "BUGGGGG"); - - window->maximized_horizontally = + + window->maximized_horizontally = window->maximized_horizontally && !unmaximize_horizontally; - window->maximized_vertically = + window->maximized_vertically = window->maximized_vertically && !unmaximize_vertically; /* Unmaximize to the saved_rect position in the direction(s) @@ -2917,21 +3013,21 @@ meta_window_make_fullscreen_internal (MetaWindow *window) /* Shading sucks anyway; I'm not adding a timestamp argument * to this function just for this niche usage & corner case. */ - guint32 timestamp = + guint32 timestamp = meta_display_get_current_time_roundtrip (window->display); meta_window_unshade (window, timestamp); } meta_window_save_rect (window); - + window->fullscreen = TRUE; meta_stack_freeze (window->screen->stack); meta_window_update_layer (window); - + meta_window_raise (window); meta_stack_thaw (window->screen->stack); - + recalc_window_features (window); set_net_wm_state (window); } @@ -2958,7 +3054,7 @@ meta_window_unmake_fullscreen (MetaWindow *window) meta_topic (META_DEBUG_WINDOW_OPS, "Unfullscreening %s\n", window->desc); - + window->fullscreen = FALSE; target_rect = window->saved_rect; @@ -2975,7 +3071,7 @@ meta_window_unmake_fullscreen (MetaWindow *window) target_rect.height); meta_window_update_layer (window); - + recalc_window_features (window); set_net_wm_state (window); } @@ -3016,7 +3112,7 @@ meta_window_shade (MetaWindow *window, meta_topic (META_DEBUG_WINDOW_OPS, "Shading %s\n", window->desc); if (!window->shaded) - { + { window->shaded = TRUE; meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); @@ -3028,7 +3124,7 @@ meta_window_shade (MetaWindow *window, "Re-focusing window %s after shading it\n", window->desc); meta_window_focus (window, timestamp); - + set_net_wm_state (window); } } @@ -3101,7 +3197,7 @@ window_activate (MetaWindow *window, return; } - /* For those stupid pagers, get a valid timestamp and show a warning */ + /* For those stupid pagers, get a valid timestamp and show a warning */ if (timestamp == 0) { meta_warning ("meta_window_activate called by a pager with a 0 timestamp; " @@ -3113,13 +3209,13 @@ window_activate (MetaWindow *window, /* disable show desktop mode unless we're a desktop component */ maybe_leave_show_desktop_mode (window); - + /* Get window on current or given workspace */ if (workspace == NULL) workspace = window->screen->active_workspace; if (!meta_window_located_on_workspace (window, workspace)) meta_window_change_workspace (window, workspace); - + if (window->shaded) meta_window_unshade (window, timestamp); @@ -3178,7 +3274,7 @@ adjust_for_gravity (MetaWindow *window, int bw; int child_x, child_y; int frame_width, frame_height; - + if (coords_assume_border) bw = window->border_width; else @@ -3198,7 +3294,7 @@ adjust_for_gravity (MetaWindow *window, frame_width = rect->width; frame_height = rect->height; } - + /* We're computing position to pass to window_move, which is * the position of the client window (StaticGravity basically) * @@ -3313,7 +3409,7 @@ send_sync_request (MetaWindow *window) window->sync_request_serial++; XSyncIntToValue (&value, window->sync_request_serial); - + ev.type = ClientMessage; ev.window = window->xwindow; ev.message_type = window->display->atom_WM_PROTOCOLS; @@ -3404,26 +3500,26 @@ meta_window_move_resize_internal (MetaWindow *window, int client_move_y; MetaRectangle new_rect; MetaRectangle old_rect; - + is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0; do_gravity_adjust = (flags & META_DO_GRAVITY_ADJUST) != 0; is_user_action = (flags & META_IS_USER_ACTION) != 0; /* The action has to be a move or a resize or both... */ g_assert (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)); - + /* We don't need it in the idle queue anymore. */ meta_window_unqueue (window, META_QUEUE_MOVE_RESIZE); meta_window_get_client_root_coords (window, &old_rect); - + meta_topic (META_DEBUG_GEOMETRY, "Move/resize %s to %d,%d %dx%d%s%s from %d,%d %dx%d\n", window->desc, root_x_nw, root_y_nw, w, h, is_configure_request ? " (configure request)" : "", is_user_action ? " (user move/resize)" : "", old_rect.x, old_rect.y, old_rect.width, old_rect.height); - + if (window->frame) meta_frame_calc_geometry (window->frame, &fgeom); @@ -3437,9 +3533,9 @@ meta_window_move_resize_internal (MetaWindow *window, * instead obtained by resizing the old rectangle according to the * relevant gravity. */ - if ((flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)) == + if ((flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)) == META_IS_RESIZE_ACTION) - { + { meta_rectangle_resize_with_gravity (&old_rect, &new_rect, gravity, @@ -3451,7 +3547,7 @@ meta_window_move_resize_internal (MetaWindow *window, new_rect.x, new_rect.y); } else if (is_configure_request || do_gravity_adjust) - { + { adjust_for_gravity (window, window->frame ? &fgeom : NULL, /* configure request coords assume @@ -3478,14 +3574,14 @@ meta_window_move_resize_internal (MetaWindow *window, h = new_rect.height; root_x_nw = new_rect.x; root_y_nw = new_rect.y; - + if (w != window->rect.width || h != window->rect.height) - need_resize_client = TRUE; - + need_resize_client = TRUE; + window->rect.width = w; window->rect.height = h; - + if (window->frame) { int new_w, new_h; @@ -3501,7 +3597,7 @@ meta_window_move_resize_internal (MetaWindow *window, frame_size_dy = new_h - window->frame->rect.height; need_resize_frame = (frame_size_dx != 0 || frame_size_dy != 0); - + window->frame->rect.width = new_w; window->frame->rect.height = new_h; @@ -3530,12 +3626,12 @@ meta_window_move_resize_internal (MetaWindow *window, * behavior. The move and resize must actually occur, it is not * enough to set CWX | CWWidth but pass in the current size/pos. */ - + if (window->frame) { int new_x, new_y; int frame_pos_dx, frame_pos_dy; - + /* Compute new frame coords */ new_x = root_x_nw - fgeom.left_width; new_y = root_y_nw - fgeom.top_height; @@ -3544,9 +3640,9 @@ meta_window_move_resize_internal (MetaWindow *window, frame_pos_dy = new_y - window->frame->rect.y; need_move_frame = (frame_pos_dx != 0 || frame_pos_dy != 0); - + window->frame->rect.x = new_x; - window->frame->rect.y = new_y; + window->frame->rect.y = new_y; /* If frame will both move and resize, then StaticGravity * on the child window will kick in and implicitly move @@ -3560,7 +3656,7 @@ meta_window_move_resize_internal (MetaWindow *window, /* window->rect.x, window->rect.y are relative to frame, * remember they are the server coords */ - + new_x = fgeom.left_width; new_y = fgeom.top_height; @@ -3573,7 +3669,7 @@ meta_window_move_resize_internal (MetaWindow *window, /* when we move the frame by frame_pos_dx, frame_pos_dy the * client will implicitly move relative to frame by the * inverse delta. - * + * * When moving client then frame, we move the client by the * frame delta, to be canceled out by the implicit move by * the inverse frame delta, resulting in a client at new_x, @@ -3587,7 +3683,7 @@ meta_window_move_resize_internal (MetaWindow *window, * In both cases we need to move the client window * in all cases where we had to move the frame window. */ - + client_move_x = new_x + frame_pos_dx; client_move_y = new_y + frame_pos_dy; @@ -3611,7 +3707,7 @@ meta_window_move_resize_internal (MetaWindow *window, /* This is the final target position, but not necessarily what * we pass to XConfigureWindow, due to StaticGravity implicit * movement. - */ + */ window->rect.x = new_x; window->rect.y = new_y; } @@ -3620,7 +3716,7 @@ meta_window_move_resize_internal (MetaWindow *window, if (root_x_nw != window->rect.x || root_y_nw != window->rect.y) need_move_client = TRUE; - + window->rect.x = root_x_nw; window->rect.y = root_y_nw; @@ -3647,9 +3743,9 @@ meta_window_move_resize_internal (MetaWindow *window, } /* See ICCCM 4.1.5 for when to send ConfigureNotify */ - + need_configure_notify = FALSE; - + /* If this is a configure request and we change nothing, then we * must send configure notify. */ @@ -3677,7 +3773,7 @@ meta_window_move_resize_internal (MetaWindow *window, ((window->size_hints.flags & PPosition) || (window->size_hints.flags & USPosition))) need_configure_notify = TRUE; - + /* The rest of this function syncs our new size/pos with X as * efficiently as possible */ @@ -3690,8 +3786,8 @@ meta_window_move_resize_internal (MetaWindow *window, configure_frame_first = (size_dx + size_dy >= 0); if (use_static_gravity) - meta_window_set_gravity (window, StaticGravity); - + meta_window_set_gravity (window, StaticGravity); + if (configure_frame_first && window->frame) meta_frame_sync_to_window (window->frame, gravity, @@ -3702,7 +3798,7 @@ meta_window_move_resize_internal (MetaWindow *window, values.y = client_move_y; values.width = window->rect.width; values.height = window->rect.height; - + mask = 0; if (is_configure_request && window->border_width != 0) mask |= CWBorderWidth; /* must force to 0 */ @@ -3724,7 +3820,7 @@ meta_window_move_resize_internal (MetaWindow *window, need_move_client ? "true" : "false", need_resize_client ? "true" : "false"); } - + meta_error_trap_push (window->display); #ifdef HAVE_XSYNC @@ -3733,7 +3829,7 @@ meta_window_move_resize_internal (MetaWindow *window, window->sync_request_time.tv_usec == 0 && window->sync_request_time.tv_sec == 0) { - /* turn off updating */ + /* turn off updating */ if (window->display->compositor) meta_compositor_set_updates (window->display->compositor, window, FALSE); @@ -3745,19 +3841,19 @@ meta_window_move_resize_internal (MetaWindow *window, window->xwindow, mask, &values); - + meta_error_trap_pop (window->display, FALSE); } if (!configure_frame_first && window->frame) meta_frame_sync_to_window (window->frame, gravity, - need_move_frame, need_resize_frame); + need_move_frame, need_resize_frame); /* Put gravity back to be nice to lesser window managers */ if (use_static_gravity) - meta_window_set_gravity (window, NorthWestGravity); - + meta_window_set_gravity (window, NorthWestGravity); + if (need_configure_notify) send_configure_notify (window); @@ -3783,12 +3879,12 @@ meta_window_move_resize_internal (MetaWindow *window, { meta_topic (META_DEBUG_GEOMETRY, "Size/position not modified\n"); } - + if (window->display->grab_wireframe_active) meta_window_update_wireframe (window, root_x_nw, root_y_nw, w, h); else meta_window_refresh_resize_popup (window); - + /* Invariants leaving this function are: * a) window->rect and frame->rect reflect the actual * server-side size/pos of window->xwindow and frame->xwindow @@ -3806,7 +3902,7 @@ meta_window_resize (MetaWindow *window, MetaMoveResizeFlags flags; meta_window_get_position (window, &x, &y); - + flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_RESIZE_ACTION; meta_window_move_resize_internal (window, flags, @@ -3820,7 +3916,7 @@ meta_window_move (MetaWindow *window, int root_x_nw, int root_y_nw) { - MetaMoveResizeFlags flags = + MetaMoveResizeFlags flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION; meta_window_move_resize_internal (window, flags, @@ -3838,8 +3934,8 @@ meta_window_move_resize (MetaWindow *window, int w, int h) { - MetaMoveResizeFlags flags = - (user_op ? META_IS_USER_ACTION : 0) | + MetaMoveResizeFlags flags = + (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION; meta_window_move_resize_internal (window, flags, @@ -3859,7 +3955,7 @@ meta_window_resize_with_gravity (MetaWindow *window, MetaMoveResizeFlags flags; meta_window_get_position (window, &x, &y); - + flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_RESIZE_ACTION; meta_window_move_resize_internal (window, flags, @@ -3900,7 +3996,7 @@ idle_move_resize (gpointer data) queue_idle[queue_index] = 0; destroying_windows_disallowed += 1; - + tmp = copy; while (tmp != NULL) { @@ -3909,15 +4005,15 @@ idle_move_resize (gpointer data) window = tmp->data; /* As a side effect, sets window->move_resize_queued = FALSE */ - meta_window_move_resize_now (window); - + meta_window_move_resize_now (window); + tmp = tmp->next; } g_slist_free (copy); destroying_windows_disallowed -= 1; - + return FALSE; } @@ -3935,7 +4031,7 @@ meta_window_configure_notify (MetaWindow *window, XConfigureEvent *event) window->rect.height = event->height; if (!event->override_redirect && !event->send_event) meta_warning ("Unhandled change of windows override redirect status\n"); - + meta_compositor_sync_window_geometry (window->display->compositor, window); } @@ -3978,7 +4074,7 @@ meta_window_get_gravity_position (MetaWindow *window, MetaRectangle frame_extents; int w, h; int x, y; - + w = window->rect.width; h = window->rect.height; @@ -4001,7 +4097,7 @@ meta_window_get_gravity_position (MetaWindow *window, x = frame_extents.x; y = frame_extents.y; - + switch (gravity) { case NorthGravity: @@ -4012,7 +4108,7 @@ meta_window_get_gravity_position (MetaWindow *window, /* Center client window on that point. */ x -= w / 2; break; - + case SouthEastGravity: case EastGravity: case NorthEastGravity: @@ -4024,7 +4120,7 @@ meta_window_get_gravity_position (MetaWindow *window, default: break; } - + switch (gravity) { case WestGravity: @@ -4046,7 +4142,7 @@ meta_window_get_gravity_position (MetaWindow *window, default: break; } - + if (root_x) *root_x = x; if (root_y) @@ -4122,7 +4218,7 @@ meta_window_get_wireframe_geometry (MetaWindow *window, return; } - *width = window->display->grab_wireframe_rect.width - + *width = window->display->grab_wireframe_rect.width - window->display->grab_window->size_hints.base_width; *width /= window->display->grab_window->size_hints.width_inc; @@ -4228,7 +4324,7 @@ get_modal_transient (MetaWindow *window) while (tmp != NULL) { MetaWindow *transient = tmp->data; - + if (transient->xtransient_for == modal_transient->xwindow && transient->wm_state_modal) { @@ -4236,7 +4332,7 @@ get_modal_transient (MetaWindow *window) tmp = windows; continue; } - + tmp = tmp->next; } @@ -4252,13 +4348,13 @@ get_modal_transient (MetaWindow *window) void meta_window_focus (MetaWindow *window, guint32 timestamp) -{ +{ MetaWindow *modal_transient; meta_topic (META_DEBUG_FOCUS, "Setting input focus to window %s, input: %d take_focus: %d\n", window->desc, window->input, window->take_focus); - + if (window->display->grab_window && window->display->grab_window->all_keys_grabbed) { @@ -4277,7 +4373,7 @@ meta_window_focus (MetaWindow *window, window->desc, modal_transient->desc); if (!modal_transient->on_all_workspaces && modal_transient->workspace != window->screen->active_workspace) - meta_window_change_workspace (modal_transient, + meta_window_change_workspace (modal_transient, window->screen->active_workspace); window = modal_transient; } @@ -4324,7 +4420,7 @@ meta_window_focus (MetaWindow *window, FALSE, timestamp); } - + if (window->take_focus) { meta_topic (META_DEBUG_FOCUS, @@ -4349,8 +4445,8 @@ meta_window_change_workspace_without_transients (MetaWindow *window, { meta_verbose ("Changing window %s to workspace %d\n", window->desc, meta_workspace_index (workspace)); - - /* unstick if stuck. meta_window_unstick would call + + /* unstick if stuck. meta_window_unstick would call * meta_window_change_workspace recursively if the window * is not in the active workspace. */ @@ -4388,12 +4484,12 @@ meta_window_change_workspace (MetaWindow *window, static void window_stick_impl (MetaWindow *window) { - GList *tmp; + GList *tmp; MetaWorkspace *workspace; meta_verbose ("Sticking window %s current on_all_workspaces = %d\n", window->desc, window->on_all_workspaces); - + if (window->on_all_workspaces) return; @@ -4416,7 +4512,7 @@ window_stick_impl (MetaWindow *window) } meta_window_set_current_workspace_hint (window); - + meta_window_queue(window, META_QUEUE_CALC_SHOWING); } @@ -4450,9 +4546,9 @@ window_unstick_impl (MetaWindow *window) */ if (window->screen->active_workspace != window->workspace) meta_window_change_workspace (window, window->screen->active_workspace); - + meta_window_set_current_workspace_hint (window); - + meta_window_queue(window, META_QUEUE_CALC_SHOWING); } @@ -4539,15 +4635,15 @@ meta_window_set_current_workspace_hint (MetaWindow *window) if (window->workspace == NULL) { - /* this happens when unmanaging windows */ + /* this happens when unmanaging windows */ return; } - + data[0] = meta_window_get_net_wm_desktop (window); meta_verbose ("Setting _NET_WM_DESKTOP of %s to %lu\n", window->desc, data[0]); - + meta_error_trap_push (window->display); XChangeProperty (window->display->xdisplay, window->xwindow, window->display->atom__NET_WM_DESKTOP, @@ -4587,7 +4683,7 @@ meta_window_raise (MetaWindow *window) ancestor = meta_window_find_root_ancestor (window); meta_topic (META_DEBUG_WINDOW_OPS, - "Raising window %s, ancestor of %s\n", + "Raising window %s, ancestor of %s\n", ancestor->desc, window->desc); /* Raise the ancestor of the window (if the window has no ancestor, @@ -4637,7 +4733,7 @@ meta_window_send_icccm_message (MetaWindow *window, /* This comment and code are from twm, copyright * Open Group, Evans & Sutherland, etc. */ - + /* * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all * client messages will have the following form: @@ -4649,9 +4745,9 @@ meta_window_send_icccm_message (MetaWindow *window, * data[0] message atom * data[1] time stamp */ - + XClientMessageEvent ev; - + ev.type = ClientMessage; ev.window = window->xwindow; ev.message_type = window->display->atom_WM_PROTOCOLS; @@ -4686,7 +4782,7 @@ meta_window_move_resize_request (MetaWindow *window, * * Still have to do the ConfigureNotify and all, but pretend the * app asked for the current size/position instead of the new one. - */ + */ in_grab_op = FALSE; if (window->display->grab_op != META_GRAB_OP_NONE && window == window->display->grab_window) @@ -4708,7 +4804,7 @@ meta_window_move_resize_request (MetaWindow *window, break; } } - + /* it's essential to use only the explicitly-set fields, * and otherwise use our current up-to-date position. * @@ -4722,7 +4818,7 @@ meta_window_move_resize_request (MetaWindow *window, &x, &y); allow_position_change = FALSE; - + if (meta_prefs_get_disable_workarounds ()) { if (window->type == META_WINDOW_DIALOG || @@ -4744,7 +4840,7 @@ meta_window_move_resize_request (MetaWindow *window, if (in_grab_op) allow_position_change = FALSE; - + if (allow_position_change) { if (value_mask & CWX) @@ -4762,10 +4858,10 @@ meta_window_move_resize_request (MetaWindow *window, else { meta_topic (META_DEBUG_GEOMETRY, - "Not allowing position change for window %s PPosition 0x%lx USPosition 0x%lx type %u\n", - window->desc, window->size_hints.flags & PPosition, + "Not allowing position change for window %s PPosition 0x%lx USPosition 0x%lx type %u\n", + window->desc, window->size_hints.flags & PPosition, window->size_hints.flags & USPosition, - window->type); + window->type); } width = window->rect.width; @@ -4774,13 +4870,13 @@ meta_window_move_resize_request (MetaWindow *window, { if (value_mask & CWWidth) width = new_width; - + if (value_mask & CWHeight) height = new_height; } /* ICCCM 4.1.5 */ - + /* We're ignoring the value_mask here, since sizes * not in the mask will be the current window geometry. */ @@ -4809,7 +4905,7 @@ meta_window_move_resize_request (MetaWindow *window, flags |= META_IS_RESIZE_ACTION; if (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)) - meta_window_move_resize_internal (window, + meta_window_move_resize_internal (window, flags, gravity, x, @@ -4850,7 +4946,7 @@ meta_window_configure_request (MetaWindow *window, event->xconfigurerequest.y, event->xconfigurerequest.width, event->xconfigurerequest.height); - + /* Handle stacking. We only handle raises/lowers, mostly because * stack.c really can't deal with anything else. I guess we'll fix * that if a client turns up that really requires it. Only a very @@ -4909,8 +5005,8 @@ meta_window_configure_request (MetaWindow *window, break; } } - } - + } + return TRUE; } @@ -4918,7 +5014,7 @@ gboolean meta_window_property_notify (MetaWindow *window, XEvent *event) { - return process_property_notify (window, &event->xproperty); + return process_property_notify (window, &event->xproperty); } /* @@ -4996,7 +5092,7 @@ meta_window_client_message (MetaWindow *window, window->desc); timestamp = meta_display_get_current_time (window->display); } - + meta_window_delete (window, timestamp); return TRUE; @@ -5006,9 +5102,9 @@ meta_window_client_message (MetaWindow *window, { int space; MetaWorkspace *workspace; - + space = event->xclient.data.l[0]; - + meta_verbose ("Request to move %s to workspace %d\n", window->desc, space); @@ -5033,7 +5129,7 @@ meta_window_client_message (MetaWindow *window, meta_verbose ("Window %s now on_all_workspaces = %d\n", window->desc, window->on_all_workspaces); - + return TRUE; } else if (event->xclient.message_type == @@ -5046,7 +5142,7 @@ meta_window_client_message (MetaWindow *window, action = event->xclient.data.l[0]; first = event->xclient.data.l[1]; second = event->xclient.data.l[2]; - + if (meta_is_verbose ()) { char *str1; @@ -5058,10 +5154,10 @@ meta_window_client_message (MetaWindow *window, str1 = NULL; meta_error_trap_push_with_return (display); - str2 = XGetAtomName (display->xdisplay, second); + str2 = XGetAtomName (display->xdisplay, second); if (meta_error_trap_pop_with_return (display, TRUE) != Success) str2 = NULL; - + meta_verbose ("Request to change _NET_WM_STATE action %lu atom1: %s atom2: %s\n", action, str1 ? str1 : "(unknown)", @@ -5079,7 +5175,7 @@ meta_window_client_message (MetaWindow *window, /* Stupid protocol has no timestamp; of course, shading * sucks anyway so who really cares that we're forced to do - * a roundtrip here? + * a roundtrip here? */ timestamp = meta_display_get_current_time_roundtrip (window->display); @@ -5103,14 +5199,14 @@ meta_window_client_message (MetaWindow *window, else meta_window_unmake_fullscreen (window); } - + if (first == display->atom__NET_WM_STATE_MAXIMIZED_HORZ || second == display->atom__NET_WM_STATE_MAXIMIZED_HORZ) { gboolean max; max = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && + (action == _NET_WM_STATE_TOGGLE && !window->maximized_horizontally)); if (max && window->has_maximize_func) { @@ -5132,7 +5228,7 @@ meta_window_client_message (MetaWindow *window, gboolean max; max = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && + (action == _NET_WM_STATE_TOGGLE && !window->maximized_vertically)); if (max && window->has_maximize_func) { @@ -5154,7 +5250,7 @@ meta_window_client_message (MetaWindow *window, window->wm_state_modal = (action == _NET_WM_STATE_ADD) || (action == _NET_WM_STATE_TOGGLE && !window->wm_state_modal); - + recalc_window_type (window); meta_window_queue(window, META_QUEUE_MOVE_RESIZE); } @@ -5162,7 +5258,7 @@ meta_window_client_message (MetaWindow *window, if (first == display->atom__NET_WM_STATE_SKIP_PAGER || second == display->atom__NET_WM_STATE_SKIP_PAGER) { - window->wm_state_skip_pager = + window->wm_state_skip_pager = (action == _NET_WM_STATE_ADD) || (action == _NET_WM_STATE_TOGGLE && !window->skip_pager); @@ -5184,7 +5280,7 @@ meta_window_client_message (MetaWindow *window, if (first == display->atom__NET_WM_STATE_ABOVE || second == display->atom__NET_WM_STATE_ABOVE) { - window->wm_state_above = + window->wm_state_above = (action == _NET_WM_STATE_ADD) || (action == _NET_WM_STATE_TOGGLE && !window->wm_state_above); @@ -5195,7 +5291,7 @@ meta_window_client_message (MetaWindow *window, if (first == display->atom__NET_WM_STATE_BELOW || second == display->atom__NET_WM_STATE_BELOW) { - window->wm_state_below = + window->wm_state_below = (action == _NET_WM_STATE_ADD) || (action == _NET_WM_STATE_TOGGLE && !window->wm_state_below); @@ -5212,7 +5308,7 @@ meta_window_client_message (MetaWindow *window, else meta_window_unset_demands_attention (window); } - + if (first == display->atom__NET_WM_STATE_STICKY || second == display->atom__NET_WM_STATE_STICKY) { @@ -5222,7 +5318,7 @@ meta_window_client_message (MetaWindow *window, else meta_window_unstick (window); } - + return TRUE; } else if (event->xclient.message_type == @@ -5252,7 +5348,7 @@ meta_window_client_message (MetaWindow *window, * "frame action". */ gboolean const frame_action = TRUE; - + x_root = event->xclient.data.l[0]; y_root = event->xclient.data.l[1]; action = event->xclient.data.l[2]; @@ -5267,7 +5363,7 @@ meta_window_client_message (MetaWindow *window, "Received _NET_WM_MOVERESIZE message on %s, %d,%d action = %d, button %d\n", window->desc, x_root, y_root, action, button); - + op = META_GRAB_OP_NONE; switch (action) { @@ -5286,7 +5382,7 @@ meta_window_client_message (MetaWindow *window, case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: op = META_GRAB_OP_RESIZING_SE; break; - case _NET_WM_MOVERESIZE_SIZE_BOTTOM: + case _NET_WM_MOVERESIZE_SIZE_BOTTOM: op = META_GRAB_OP_RESIZING_S; break; case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: @@ -5316,8 +5412,8 @@ meta_window_client_message (MetaWindow *window, } else if (op != META_GRAB_OP_NONE && ((window->has_move_func && op == META_GRAB_OP_MOVING) || - (window->has_resize_func && - (op != META_GRAB_OP_MOVING && + (window->has_resize_func && + (op != META_GRAB_OP_MOVING && op != META_GRAB_OP_KEYBOARD_MOVING)))) { /* @@ -5436,7 +5532,7 @@ meta_window_client_message (MetaWindow *window, meta_window_update_fullscreen_monitors (window, top, bottom, left, right); } - + return FALSE; } @@ -5447,7 +5543,7 @@ meta_window_notify_focus (MetaWindow *window, /* note the event can be on either the window or the frame, * we focus the frame for shaded windows */ - + /* The event can be FocusIn, FocusOut, or UnmapNotify. * On UnmapNotify we have to pretend it's focus out, * because we won't get a focus out if it occurs, apparently. @@ -5461,7 +5557,7 @@ meta_window_notify_focus (MetaWindow *window, * XGrabKey, which means focus_window disappears and the front of * the MRU list gets confused from what the user expects once a * keybinding is used. - */ + */ meta_topic (META_DEBUG_FOCUS, "Focus %s event received on %s 0x%lx (%s) " "mode %s detail %s\n", @@ -5498,7 +5594,7 @@ meta_window_notify_focus (MetaWindow *window, * * http://bugzilla.gnome.org/show_bug.cgi?id=90382 */ - + if ((event->type == FocusIn || event->type == FocusOut) && (event->xfocus.mode == NotifyGrab || @@ -5510,7 +5606,7 @@ meta_window_notify_focus (MetaWindow *window, "Ignoring focus event generated by a grab or other weirdness\n"); return TRUE; } - + if (event->type == FocusIn) { if (window != window->display->focus_window) @@ -5531,27 +5627,27 @@ meta_window_notify_focus (MetaWindow *window, * workspace. */ if (window->screen->active_workspace && - meta_window_located_on_workspace (window, + meta_window_located_on_workspace (window, window->screen->active_workspace)) { GList* link; - link = g_list_find (window->screen->active_workspace->mru_list, + link = g_list_find (window->screen->active_workspace->mru_list, window); g_assert (link); - window->screen->active_workspace->mru_list = + window->screen->active_workspace->mru_list = g_list_remove_link (window->screen->active_workspace->mru_list, link); g_list_free (link); - window->screen->active_workspace->mru_list = - g_list_prepend (window->screen->active_workspace->mru_list, + window->screen->active_workspace->mru_list = + g_list_prepend (window->screen->active_workspace->mru_list, window); } if (window->frame) meta_frame_queue_draw (window->frame); - + meta_error_trap_push (window->display); XInstallColormap (window->display->xdisplay, window->colormap); @@ -5590,7 +5686,7 @@ meta_window_notify_focus (MetaWindow *window, window->desc); return TRUE; } - + if (window == window->display->focus_window) { meta_topic (META_DEBUG_FOCUS, @@ -5599,13 +5695,13 @@ meta_window_notify_focus (MetaWindow *window, meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL (was %s)\n", window->desc); - + window->display->focus_window = NULL; window->has_focus = FALSE; if (window->frame) meta_frame_queue_draw (window->frame); - meta_compositor_set_active_window (window->display->compositor, + meta_compositor_set_active_window (window->display->compositor, window->screen, NULL); meta_error_trap_push (window->display); @@ -5625,7 +5721,7 @@ meta_window_notify_focus (MetaWindow *window, /* Now set _NET_ACTIVE_WINDOW hint */ meta_display_update_active_window_hint (window->display); - + return FALSE; } @@ -5658,7 +5754,7 @@ process_property_notify (MetaWindow *window, window->desc, property_name); XFree (property_name); } - + if (event->atom == XA_WM_NAME) { /* don't bother reloading WM_NAME if using _NET_WM_NAME already */ @@ -5668,10 +5764,10 @@ process_property_notify (MetaWindow *window, else if (event->atom == window->display->atom__NET_WM_NAME) { meta_window_reload_property (window, window->display->atom__NET_WM_NAME); - + /* if _NET_WM_NAME was unset, reload WM_NAME */ if (!window->using_net_wm_name) - meta_window_reload_property (window, XA_WM_NAME); + meta_window_reload_property (window, XA_WM_NAME); } else if (event->atom == XA_WM_ICON_NAME) { @@ -5682,15 +5778,15 @@ process_property_notify (MetaWindow *window, else if (event->atom == window->display->atom__NET_WM_ICON_NAME) { meta_window_reload_property (window, window->display->atom__NET_WM_ICON_NAME); - + /* if _NET_WM_ICON_NAME was unset, reload WM_ICON_NAME */ if (!window->using_net_wm_icon_name) meta_window_reload_property (window, XA_WM_ICON_NAME); - } + } else if (event->atom == XA_WM_NORMAL_HINTS) { meta_window_reload_property (window, XA_WM_NORMAL_HINTS); - + /* See if we need to constrain current size */ meta_window_queue(window, META_QUEUE_MOVE_RESIZE); } @@ -5785,7 +5881,7 @@ send_configure_notify (MetaWindow *window) XEvent event; /* from twm */ - + event.type = ConfigureNotify; event.xconfigure.display = window->display->xdisplay; event.xconfigure.event = window->xwindow; @@ -5820,7 +5916,7 @@ send_configure_notify (MetaWindow *window) window->desc, event.xconfigure.x, event.xconfigure.y, event.xconfigure.width, event.xconfigure.height); - + meta_error_trap_push (window->display); XSendEvent (window->display->xdisplay, window->xwindow, @@ -5847,7 +5943,7 @@ meta_window_get_icon_geometry (MetaWindow *window, meta_XFree (geometry); return FALSE; } - + if (rect) { rect->x = geometry[0]; @@ -5869,7 +5965,7 @@ read_client_leader (MetaDisplay *display, Window xwindow) { Window retval = None; - + meta_prop_get_window (display, xwindow, display->atom_WM_CLIENT_LEADER, &retval); @@ -5879,7 +5975,7 @@ read_client_leader (MetaDisplay *display, typedef struct { - Window leader; + Window leader; } ClientLeaderData; static gboolean @@ -5901,7 +5997,7 @@ static void update_sm_hints (MetaWindow *window) { Window leader; - + window->xclient_leader = None; window->sm_client_id = NULL; @@ -5918,11 +6014,11 @@ update_sm_hints (MetaWindow *window) &d); leader = d.leader; } - + if (leader != None) { char *str; - + window->xclient_leader = leader; if (meta_prop_get_latin1_string (window->display, leader, @@ -5952,7 +6048,7 @@ update_sm_hints (MetaWindow *window) if (window->sm_client_id == NULL) /* first time through */ meta_warning (_("Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n"), window->desc); - + window->sm_client_id = g_strdup (str); meta_XFree (str); } @@ -5968,7 +6064,7 @@ static void update_role (MetaWindow *window) { char *str; - + if (window->role) g_free (window->role); window->role = NULL; @@ -5995,8 +6091,8 @@ update_net_wm_type (MetaWindow *window) window->type_atom = None; n_atoms = 0; atoms = NULL; - - meta_prop_get_atom_list (window->display, window->xwindow, + + meta_prop_get_atom_list (window->display, window->xwindow, window->display->atom__NET_WM_WINDOW_TYPE, &atoms, &n_atoms); @@ -6026,10 +6122,10 @@ update_net_wm_type (MetaWindow *window) window->type_atom = atoms[i]; break; } - + ++i; } - + meta_XFree (atoms); if (meta_is_verbose ()) @@ -6050,7 +6146,7 @@ update_net_wm_type (MetaWindow *window) if (str) meta_XFree (str); } - + recalc_window_type (window); } @@ -6072,7 +6168,7 @@ meta_window_update_icon_now (MetaWindow *window) icon = NULL; mini_icon = NULL; - + if (meta_read_icons (window->screen, window->xwindow, &window->icon_cache, @@ -6086,16 +6182,21 @@ meta_window_update_icon_now (MetaWindow *window) { if (window->icon) g_object_unref (G_OBJECT (window->icon)); - + if (window->mini_icon) g_object_unref (G_OBJECT (window->mini_icon)); - + window->icon = icon; window->mini_icon = mini_icon; + g_object_freeze_notify (G_OBJECT (window)); + g_object_notify (G_OBJECT (window), "icon"); + g_object_notify (G_OBJECT (window), "mini-icon"); + g_object_thaw_notify (G_OBJECT (window)); + redraw_icon (window); } - + g_assert (window->icon); g_assert (window->mini_icon); } @@ -6119,7 +6220,7 @@ idle_update_icon (gpointer data) queue_idle[queue_index] = 0; destroying_windows_disallowed += 1; - + tmp = copy; while (tmp != NULL) { @@ -6127,16 +6228,16 @@ idle_update_icon (gpointer data) window = tmp->data; - meta_window_update_icon_now (window); + meta_window_update_icon_now (window); window->is_in_queues &= ~META_QUEUE_UPDATE_ICON; - + tmp = tmp->next; } g_slist_free (copy); destroying_windows_disallowed -= 1; - + return FALSE; } @@ -6155,7 +6256,7 @@ invalidate_work_areas (MetaWindow *window) GList *tmp; tmp = meta_window_get_workspaces (window); - + while (tmp != NULL) { meta_workspace_invalidate_work_area (tmp->data); @@ -6176,7 +6277,7 @@ meta_window_update_struts (MetaWindow *window) meta_verbose ("Updating struts for %s\n", window->desc); old_struts = window->struts; - new_struts = NULL; + new_struts = NULL; if (meta_prop_get_cardinal_list (window->display, window->xwindow, @@ -6232,7 +6333,7 @@ meta_window_update_struts (MetaWindow *window) meta_verbose ("_NET_WM_STRUT_PARTIAL struts %lu %lu %lu %lu for " "window %s\n", - struts[0], struts[1], struts[2], struts[3], + struts[0], struts[1], struts[2], struts[3], window->desc); } meta_XFree (struts); @@ -6288,9 +6389,9 @@ meta_window_update_struts (MetaWindow *window) new_struts = g_slist_prepend (new_struts, temp); } - + meta_verbose ("_NET_WM_STRUT struts %lu %lu %lu %lu for window %s\n", - struts[0], struts[1], struts[2], struts[3], + struts[0], struts[1], struts[2], struts[3], window->desc); } meta_XFree (struts); @@ -6300,7 +6401,7 @@ meta_window_update_struts (MetaWindow *window) meta_verbose ("No _NET_WM_STRUT property for %s\n", window->desc); } - + /* Determine whether old_struts and new_struts are the same */ old_iter = old_struts; new_iter = new_struts; @@ -6347,7 +6448,7 @@ recalc_window_type (MetaWindow *window) MetaWindowType old_type; old_type = window->type; - + if (window->override_redirect) { if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU) @@ -6399,23 +6500,23 @@ recalc_window_type (MetaWindow *window) if (window->type == META_WINDOW_DIALOG && window->wm_state_modal) window->type = META_WINDOW_MODAL_DIALOG; - + meta_verbose ("Calculated type %u for %s, old type %u\n", window->type, window->desc, old_type); if (old_type != window->type) { recalc_window_features (window); - + if (!window->override_redirect) set_net_wm_state (window); - + /* Update frame */ if (window->decorated) meta_window_ensure_frame (window); else meta_window_destroy_frame (window); - + /* update stacking constraints */ meta_window_update_layer (window); @@ -6484,7 +6585,7 @@ set_allowed_actions_hint (MetaWindow *window) g_assert (i <= MAX_N_ACTIONS); meta_verbose ("Setting _NET_WM_ALLOWED_ACTIONS with %d atoms\n", i); - + meta_error_trap_push (window->display); XChangeProperty (window->display->xdisplay, window->xwindow, window->display->atom__NET_WM_ALLOWED_ACTIONS, @@ -6524,8 +6625,8 @@ recalc_window_features (MetaWindow *window) window->has_minimize_func = window->mwm_has_minimize_func; window->has_maximize_func = window->mwm_has_maximize_func; window->has_move_func = window->mwm_has_move_func; - - window->has_resize_func = TRUE; + + window->has_resize_func = TRUE; /* If min_size == max_size, then don't allow resize */ if (window->size_hints.min_width == window->size_hints.max_width && @@ -6540,7 +6641,7 @@ recalc_window_features (MetaWindow *window) * MWM but not WM_NORMAL_HINTS are basically broken. We complain * about these apps but make them work. */ - + meta_warning (_("Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.\n"), window->desc, window->size_hints.min_width, @@ -6553,7 +6654,7 @@ recalc_window_features (MetaWindow *window) window->has_fullscreen_func = TRUE; window->always_sticky = FALSE; - + /* Semantic category overrides the MWM hints */ if (window->type == META_WINDOW_TOOLBAR) window->decorated = FALSE; @@ -6562,7 +6663,7 @@ recalc_window_features (MetaWindow *window) window->type == META_WINDOW_DOCK || window->override_redirect) window->always_sticky = TRUE; - + if (window->type == META_WINDOW_DESKTOP || window->type == META_WINDOW_DOCK || window->type == META_WINDOW_SPLASHSCREEN || @@ -6583,7 +6684,7 @@ recalc_window_features (MetaWindow *window) window->has_move_func = FALSE; window->has_resize_func = FALSE; } - + if (window->type != META_WINDOW_NORMAL) { window->has_minimize_func = FALSE; @@ -6592,9 +6693,9 @@ recalc_window_features (MetaWindow *window) } if (!window->has_resize_func) - { + { window->has_maximize_func = FALSE; - + /* don't allow fullscreen if we can't resize, unless the size * is entire screen size (kind of broken, because we * actually fullscreen to xinerama head size not screen size) @@ -6631,7 +6732,7 @@ recalc_window_features (MetaWindow *window) window->size_hints.min_height, window->size_hints.max_width, window->size_hints.max_height); - + /* no shading if not decorated */ if (!window->decorated || window->border_only) window->has_shade_func = FALSE; @@ -6641,10 +6742,10 @@ recalc_window_features (MetaWindow *window) if (window->wm_state_skip_taskbar) window->skip_taskbar = TRUE; - + if (window->wm_state_skip_pager) window->skip_pager = TRUE; - + switch (window->type) { /* Force skip taskbar/pager on these window types */ @@ -6672,7 +6773,7 @@ recalc_window_features (MetaWindow *window) window->xtransient_for != window->screen->xroot) window->skip_taskbar = TRUE; break; - + case META_WINDOW_NORMAL: break; } @@ -6689,7 +6790,7 @@ recalc_window_features (MetaWindow *window) window->has_shade_func, window->skip_taskbar, window->skip_pager); - + /* FIXME: * Lame workaround for recalc_window_features * being used overzealously. The fix is to @@ -6704,7 +6805,7 @@ recalc_window_features (MetaWindow *window) old_has_shade_func != window->has_shade_func || old_always_sticky != window->always_sticky) set_allowed_actions_hint (window); - + /* FIXME perhaps should ensure if we don't have a shade func, * we aren't shaded, etc. */ @@ -6722,15 +6823,15 @@ menu_callback (MetaWindowMenu *menu, MetaDisplay *display; MetaWindow *window; MetaWorkspace *workspace; - + display = meta_display_for_x_display (xdisplay); window = meta_display_lookup_x_window (display, client_xwindow); workspace = NULL; - + if (window != NULL) /* window can be NULL */ { meta_verbose ("Menu op %u on %s\n", op, window->desc); - + /* op can be 0 for none */ switch (op) { @@ -6747,7 +6848,7 @@ menu_callback (MetaWindowMenu *menu, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); break; - + case META_MENU_OP_MAXIMIZE: meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL | @@ -6757,11 +6858,11 @@ menu_callback (MetaWindowMenu *menu, case META_MENU_OP_UNSHADE: meta_window_unshade (window, timestamp); break; - + case META_MENU_OP_SHADE: meta_window_shade (window, timestamp); break; - + case META_MENU_OP_MOVE_LEFT: workspace = meta_workspace_get_neighbor (window->screen->active_workspace, META_MOTION_LEFT); @@ -6820,11 +6921,11 @@ menu_callback (MetaWindowMenu *menu, case META_MENU_OP_RECOVER: meta_window_shove_titlebar_onscreen (window); break; - + case 0: /* nothing */ break; - + default: meta_warning (G_STRLOC": Unknown window op\n"); break; @@ -6850,7 +6951,7 @@ menu_callback (MetaWindowMenu *menu, display->window_menu = NULL; display->window_with_menu = NULL; } - + meta_ui_window_menu_free (menu); } @@ -6867,7 +6968,7 @@ meta_window_show_menu (MetaWindow *window, MetaWorkspaceLayout layout; int n_workspaces; gboolean ltr; - + if (window->display->window_menu) { meta_ui_window_menu_free (window->display->window_menu); @@ -6917,7 +7018,7 @@ meta_window_show_menu (MetaWindow *window, ops |= META_MENU_OP_UNMAXIMIZE; else ops |= META_MENU_OP_MAXIMIZE; - + #if 0 if (window->shaded) ops |= META_MENU_OP_UNSHADE; @@ -6932,13 +7033,13 @@ meta_window_show_menu (MetaWindow *window, ops |= META_MENU_OP_UNABOVE; else ops |= META_MENU_OP_ABOVE; - + if (!window->has_maximize_func) insensitive |= META_MENU_OP_UNMAXIMIZE | META_MENU_OP_MAXIMIZE; - + if (!window->has_minimize_func) insensitive |= META_MENU_OP_MINIMIZE; - + if (!window->has_close_func) insensitive |= META_MENU_OP_DELETE; @@ -6964,7 +7065,7 @@ meta_window_show_menu (MetaWindow *window, */ if ((ops & ~insensitive) == 0) return; - + menu = meta_ui_window_menu_new (window->screen->ui, window->xwindow, @@ -6973,13 +7074,13 @@ meta_window_show_menu (MetaWindow *window, meta_window_get_net_wm_desktop (window), meta_screen_get_n_workspaces (window->screen), menu_callback, - NULL); + NULL); window->display->window_menu = menu; window->display->window_with_menu = window; - + meta_verbose ("Popping up window menu for %s\n", window->desc); - + meta_ui_window_menu_popup (menu, root_x, root_y, button, timestamp); } @@ -7007,7 +7108,7 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window) vert_amount = outer_rect.height; meta_rectangle_expand_region (onscreen_region, horiz_amount, - horiz_amount, + horiz_amount, 0, vert_amount); meta_rectangle_shove_into_region(onscreen_region, @@ -7015,7 +7116,7 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window) &outer_rect); meta_rectangle_expand_region (onscreen_region, -horiz_amount, - -horiz_amount, + -horiz_amount, 0, -vert_amount); @@ -7025,7 +7126,7 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window) FALSE, newx, newy, - window->rect.width, + window->rect.width, window->rect.height); } @@ -7044,7 +7145,7 @@ meta_window_titlebar_is_onscreen (MetaWindow *window) /* Titlebar can't be offscreen if there is no titlebar... */ if (!window->frame) return FALSE; - + /* Get the rectangle corresponding to the titlebar */ meta_window_get_outer_rect (window, &titlebar_rect); titlebar_rect.height = window->frame->child_y; @@ -7059,16 +7160,16 @@ meta_window_titlebar_is_onscreen (MetaWindow *window) { MetaRectangle *spanning_rect = onscreen_region->data; MetaRectangle overlap; - + meta_rectangle_intersect (&titlebar_rect, spanning_rect, &overlap); if (overlap.height > MIN (titlebar_rect.height, min_height_needed) && - overlap.width > MIN (titlebar_rect.width * min_width_percent, + overlap.width > MIN (titlebar_rect.width * min_width_percent, min_width_absolute)) { is_onscreen = TRUE; break; } - + onscreen_region = onscreen_region->next; } @@ -7092,11 +7193,11 @@ time_diff (const GTimeVal *first, } static gboolean -check_moveresize_frequency (MetaWindow *window, +check_moveresize_frequency (MetaWindow *window, gdouble *remaining) { GTimeVal current_time; - + g_get_current_time (¤t_time); #ifdef HAVE_XSYNC @@ -7117,7 +7218,7 @@ check_moveresize_frequency (MetaWindow *window, */ if (remaining) *remaining = 1000.0 - elapsed + 100; - + return FALSE; } else @@ -7150,17 +7251,17 @@ check_moveresize_frequency (MetaWindow *window, meta_topic (META_DEBUG_RESIZING, "Delaying move/resize as only %g of %g ms elapsed\n", elapsed, ms_between_resizes); - + if (remaining) *remaining = (ms_between_resizes - elapsed); return FALSE; } - + meta_topic (META_DEBUG_RESIZING, " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)\n", elapsed / 1000.0, 1.0 / max_resizes_per_second); - + return TRUE; } } @@ -7170,7 +7271,7 @@ update_move_timeout (gpointer data) { MetaWindow *window = data; - update_move (window, + update_move (window, window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y); @@ -7189,10 +7290,10 @@ update_move (MetaWindow *window, MetaRectangle old; int shake_threshold; MetaDisplay *display = window->display; - + display->grab_latest_motion_x = x; display->grab_latest_motion_y = y; - + dx = x - display->grab_anchor_root_x; dy = y - display->grab_anchor_root_y; @@ -7221,20 +7322,20 @@ update_move (MetaWindow *window, #define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6 shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) * DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; - + if (META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold) { double prop; /* Shake loose */ window->shaken_loose = TRUE; - + /* move the unmaximized window to the cursor */ - prop = - ((double)(x - display->grab_initial_window_pos.x)) / + prop = + ((double)(x - display->grab_initial_window_pos.x)) / ((double)display->grab_initial_window_pos.width); - display->grab_initial_window_pos.x = + display->grab_initial_window_pos.x = x - window->saved_rect.width * prop; display->grab_initial_window_pos.y = y; @@ -7269,7 +7370,7 @@ update_move (MetaWindow *window, { meta_window_get_work_area_for_xinerama (window, monitor, &work_area); - /* check if cursor is near the top of a xinerama work area */ + /* check if cursor is near the top of a xinerama work area */ if (x >= work_area.x && x < (work_area.x + work_area.width) && y >= work_area.y && @@ -7282,8 +7383,8 @@ update_move (MetaWindow *window, { window->saved_rect.x = work_area.x; window->saved_rect.y = work_area.y; - - if (window->frame) + + if (window->frame) { window->saved_rect.x += window->frame->child_x; window->saved_rect.y += window->frame->child_y; @@ -7301,7 +7402,7 @@ update_move (MetaWindow *window, display->grab_anchor_root_x = x; display->grab_anchor_root_y = y; window->shaken_loose = FALSE; - + meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); @@ -7323,7 +7424,7 @@ update_move (MetaWindow *window, new_y = old.y; /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_move (window, + meta_window_edge_resistance_for_move (window, old.x, old.y, &new_x, @@ -7336,13 +7437,13 @@ update_move (MetaWindow *window, { int root_x = new_x - display->grab_anchor_window_pos.x + display->grab_anchor_root_x; int root_y = new_y - display->grab_anchor_window_pos.y + display->grab_anchor_root_y; - + meta_compositor_update_move (display->compositor, window, root_x, root_y); } - + if (display->grab_wireframe_active) - meta_window_update_wireframe (window, new_x, new_y, + meta_window_update_wireframe (window, new_x, new_y, display->grab_wireframe_rect.width, display->grab_wireframe_rect.height); else @@ -7354,7 +7455,7 @@ update_resize_timeout (gpointer data) { MetaWindow *window = data; - update_resize (window, + update_resize (window, window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y, @@ -7374,10 +7475,10 @@ update_resize (MetaWindow *window, MetaRectangle old; int new_x, new_y; double remaining; - + window->display->grab_latest_motion_x = x; window->display->grab_latest_motion_y = y; - + dx = x - window->display->grab_anchor_root_x; dy = y - window->display->grab_anchor_root_y; @@ -7390,7 +7491,7 @@ update_resize (MetaWindow *window, */ if (dx == 0 && dy == 0) return; - + /* FIXME this is only used in wireframe mode */ new_x = window->display->grab_anchor_window_pos.x; new_y = window->display->grab_anchor_window_pos.y; @@ -7438,7 +7539,7 @@ update_resize (MetaWindow *window, meta_window_update_keyboard_resize (window, TRUE); } } - + /* FIXME: This stupidity only needed because of wireframe mode and * the fact that wireframe isn't making use of * meta_rectangle_resize_with_gravity(). If we were to use that, we @@ -7464,11 +7565,11 @@ update_resize (MetaWindow *window, new_w -= dx; new_x += dx; break; - + default: break; } - + switch (window->display->grab_op) { case META_GRAB_OP_RESIZING_SE: @@ -7479,7 +7580,7 @@ update_resize (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_SW: new_h += dy; break; - + case META_GRAB_OP_RESIZING_N: case META_GRAB_OP_RESIZING_NE: case META_GRAB_OP_RESIZING_NW: @@ -7502,7 +7603,7 @@ update_resize (MetaWindow *window, */ if (!window->display->grab_resize_timeout_id) { - window->display->grab_resize_timeout_id = + window->display->grab_resize_timeout_id = g_timeout_add ((int)remaining, update_resize_timeout, window); } @@ -7519,7 +7620,7 @@ update_resize (MetaWindow *window, g_source_remove (window->display->grab_resize_timeout_id); window->display->grab_resize_timeout_id = 0; } - + if (window->display->grab_wireframe_active) old = window->display->grab_wireframe_rect; else @@ -7535,7 +7636,7 @@ update_resize (MetaWindow *window, case META_GRAB_OP_RESIZING_N: new_w = old.width; break; - + case META_GRAB_OP_RESIZING_E: case META_GRAB_OP_RESIZING_W: new_h = old.height; @@ -7548,7 +7649,7 @@ update_resize (MetaWindow *window, /* compute gravity of client during operation */ gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); g_assert (gravity >= 0); - + /* Do any edge resistance/snapping */ meta_window_edge_resistance_for_resize (window, old.width, @@ -7620,7 +7721,7 @@ check_use_this_motion_notify (MetaWindow *window, XEvent useless; /* This code is copied from Owen's GDK code. */ - + if (window->display->grab_motion_notify_time != 0) { /* == is really the right test, but I'm all for paranoia */ @@ -7637,7 +7738,7 @@ check_use_this_motion_notify (MetaWindow *window, else return FALSE; /* haven't reached the saved timestamp yet */ } - + esd.current_event = event; esd.count = 0; esd.last_time = 0; @@ -7652,7 +7753,7 @@ check_use_this_motion_notify (MetaWindow *window, meta_topic (META_DEBUG_RESIZING, "Will skip %d motion events and use the event with time %u\n", esd.count, (unsigned int) esd.last_time); - + if (esd.last_time == 0) return TRUE; else @@ -7684,7 +7785,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, window->disable_sync = FALSE; window->sync_request_time.tv_sec = 0; window->sync_request_time.tv_usec = 0; - + /* This means we are ready for another configure. */ switch (window->display->grab_op) { @@ -7711,13 +7812,13 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, window->display->grab_latest_motion_y, TRUE); break; - + default: break; } } #endif /* HAVE_XSYNC */ - + switch (event->type) { case ButtonRelease: @@ -7751,7 +7852,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, } meta_display_end_grab_op (window->display, event->xbutton.time); - break; + break; case MotionNotify: meta_display_check_threshold_reached (window->display, @@ -7798,14 +7899,14 @@ meta_window_set_gravity (MetaWindow *window, meta_verbose ("Setting gravity of %s to %d\n", window->desc, gravity); attrs.win_gravity = gravity; - + meta_error_trap_push (window->display); XChangeWindowAttributes (window->display->xdisplay, window->xwindow, CWWinGravity, &attrs); - + meta_error_trap_pop (window->display, FALSE); } @@ -7814,14 +7915,14 @@ get_work_area_xinerama (MetaWindow *window, MetaRectangle *area, int which_xinerama) { - GList *tmp; - + GList *tmp; + g_assert (which_xinerama >= 0); /* Initialize to the whole xinerama */ *area = window->screen->xinerama_infos[which_xinerama].rect; - - tmp = meta_window_get_workspaces (window); + + tmp = meta_window_get_workspaces (window); while (tmp != NULL) { MetaRectangle workspace_work_area; @@ -7833,7 +7934,7 @@ get_work_area_xinerama (MetaWindow *window, area); tmp = tmp->next; } - + meta_topic (META_DEBUG_WORKAREA, "Window %s xinerama %d has work area %d,%d %d x %d\n", window->desc, which_xinerama, @@ -7859,7 +7960,7 @@ meta_window_get_work_area_for_xinerama (MetaWindow *window, MetaRectangle *area) { g_return_if_fail (which_xinerama >= 0); - + get_work_area_xinerama (window, area, which_xinerama); @@ -7869,12 +7970,12 @@ void meta_window_get_work_area_all_xineramas (MetaWindow *window, MetaRectangle *area) { - GList *tmp; + GList *tmp; /* Initialize to the whole screen */ *area = window->screen->rect; - - tmp = meta_window_get_workspaces (window); + + tmp = meta_window_get_workspaces (window); while (tmp != NULL) { MetaRectangle workspace_work_area; @@ -7923,7 +8024,7 @@ meta_window_refresh_resize_popup (MetaWindow *window) "refresh_resize_popup called when wireframe active\n"); return; } - + switch (window->display->grab_op) { case META_GRAB_OP_RESIZING_SE: @@ -7949,7 +8050,7 @@ meta_window_refresh_resize_popup (MetaWindow *window) /* Not resizing */ return; } - + if (window->display->grab_resize_popup == NULL) { if (window->size_hints.width_inc > 1 || @@ -7958,16 +8059,16 @@ meta_window_refresh_resize_popup (MetaWindow *window) meta_ui_resize_popup_new (window->display->xdisplay, window->screen->number); } - + if (window->display->grab_resize_popup != NULL) { MetaRectangle rect; - + if (window->display->grab_wireframe_active) rect = window->display->grab_wireframe_rect; else meta_window_get_client_root_coords (window, &rect); - + meta_ui_resize_popup_set (window->display->grab_resize_popup, rect, window->size_hints.base_width, @@ -7994,13 +8095,13 @@ meta_window_foreach_transient (MetaWindow *window, while (tmp != NULL) { MetaWindow *transient = tmp->data; - + if (meta_window_is_ancestor_of_transient (window, transient)) { if (!(* func) (transient, data)) break; } - + tmp = tmp->next; } @@ -8014,7 +8115,7 @@ meta_window_foreach_ancestor (MetaWindow *window, { MetaWindow *w; MetaWindow *tortoise; - + w = window; tortoise = window; while (TRUE) @@ -8022,27 +8123,27 @@ meta_window_foreach_ancestor (MetaWindow *window, if (w->xtransient_for == None || w->transient_parent_is_root_window) break; - + w = meta_display_lookup_x_window (w->display, w->xtransient_for); - + if (w == NULL || w == tortoise) break; if (!(* func) (w, data)) - break; - + break; + if (w->xtransient_for == None || w->transient_parent_is_root_window) break; w = meta_display_lookup_x_window (w->display, w->xtransient_for); - + if (w == NULL || w == tortoise) break; if (!(* func) (w, data)) break; - + tortoise = meta_display_lookup_x_window (tortoise->display, tortoise->xtransient_for); @@ -8106,7 +8207,7 @@ warp_grab_pointer (MetaWindow *window, /* We may not have done begin_grab_op yet, i.e. may not be in a grab */ - + if (window == display->grab_window && display->grab_wireframe_active) { meta_window_get_xor_rect (window, &display->grab_wireframe_rect, &rect); @@ -8115,7 +8216,7 @@ warp_grab_pointer (MetaWindow *window, { meta_window_get_outer_rect (window, &rect); } - + switch (grab_op) { case META_GRAB_OP_KEYBOARD_MOVING: @@ -8174,7 +8275,7 @@ warp_grab_pointer (MetaWindow *window, /* Avoid weird bouncing at the screen edge; see bug 154706 */ *x = CLAMP (*x, 0, window->screen->rect.width-1); *y = CLAMP (*y, 0, window->screen->rect.height-1); - + meta_error_trap_push_with_return (display); meta_topic (META_DEBUG_WINDOW_OPS, @@ -8194,11 +8295,11 @@ warp_grab_pointer (MetaWindow *window, else meta_window_get_client_root_coords (window, &display->grab_anchor_window_pos); - + XWarpPointer (display->xdisplay, None, window->screen->xroot, - 0, 0, 0, 0, + 0, 0, 0, 0, *x, *y); if (meta_error_trap_pop_with_return (display, FALSE) != Success) @@ -8207,7 +8308,7 @@ warp_grab_pointer (MetaWindow *window, window->desc); return FALSE; } - + return TRUE; } @@ -8239,7 +8340,7 @@ meta_window_update_keyboard_resize (MetaWindow *window, gboolean update_cursor) { int x, y; - + warp_grab_pointer (window, window->display->grab_op, &x, &y); @@ -8262,7 +8363,7 @@ void meta_window_update_keyboard_move (MetaWindow *window) { int x, y; - + warp_grab_pointer (window, window->display->grab_op, &x, &y); @@ -8272,7 +8373,7 @@ void meta_window_update_layer (MetaWindow *window) { MetaGroup *group; - + meta_stack_freeze (window->screen->stack); group = meta_window_get_group (window); if (group) @@ -8336,8 +8437,8 @@ meta_window_stack_just_below (MetaWindow *window, { meta_topic (META_DEBUG_STACK, "Setting stack position of window %s to %d (making it below window %s).\n", - window->desc, - below_this_one->stack_position, + window->desc, + below_this_one->stack_position, below_this_one->desc); meta_window_set_stack_position (window, below_this_one->stack_position); } @@ -8397,7 +8498,7 @@ meta_window_set_demands_attention (MetaWindow *window) GList *stack = window->screen->stack->sorted; MetaWindow *other_window; gboolean obscured = FALSE; - + MetaWorkspace *workspace = window->screen->active_workspace; if (workspace!=window->workspace) { @@ -8413,12 +8514,12 @@ meta_window_set_demands_attention (MetaWindow *window) meta_window_get_outer_rect (window, &candidate_rect); /* The stack is sorted with the top windows first. */ - + while (stack != NULL && stack->data != window) { other_window = stack->data; stack = stack->next; - + if (other_window->on_all_workspaces || window->on_all_workspaces || other_window->workspace == window->workspace) @@ -8459,7 +8560,7 @@ meta_window_unset_demands_attention (MetaWindow *window) { meta_topic (META_DEBUG_WINDOW_OPS, "Marking %s as not needing attention\n", window->desc); - + window->wm_state_demands_attention = FALSE; set_net_wm_state (window); } @@ -8507,13 +8608,13 @@ meta_window_get_xwindow (MetaWindow *window) } MetaWindowType -meta_window_get_type (MetaWindow *window) +meta_window_get_window_type (MetaWindow *window) { return window->type; } Atom -meta_window_get_type_atom (MetaWindow *window) +meta_window_get_window_type_atom (MetaWindow *window) { return window->type_atom; } diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h index 5b9589ccd..eab39b575 100644 --- a/src/core/workspace-private.h +++ b/src/core/workspace-private.h @@ -38,6 +38,7 @@ struct _MetaWorkspace { + GObject parent_instance; MetaScreen *screen; GList *windows; @@ -49,6 +50,7 @@ struct _MetaWorkspace MetaRectangle *work_area_xinerama; GList *screen_region; GList **xinerama_region; + gint n_xinerama_regions; GList *screen_edges; GList *xinerama_edges; GSList *all_struts; @@ -57,8 +59,13 @@ struct _MetaWorkspace guint showing_desktop : 1; }; +struct _MetaWorkspaceClass +{ + GObjectClass parent_class; +}; + MetaWorkspace* meta_workspace_new (MetaScreen *screen); -void meta_workspace_free (MetaWorkspace *workspace); +void meta_workspace_remove (MetaWorkspace *workspace); void meta_workspace_add_window (MetaWorkspace *workspace, MetaWindow *window); void meta_workspace_remove_window (MetaWorkspace *workspace, diff --git a/src/core/workspace.c b/src/core/workspace.c index 625da5087..74d7d184b 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -45,6 +45,27 @@ static void free_this (gpointer candidate, gpointer dummy); static void workspace_free_struts (MetaWorkspace *workspace); +G_DEFINE_TYPE (MetaWorkspace, meta_workspace, G_TYPE_OBJECT); + +static void +meta_workspace_finalize (GObject *object) +{ + /* Actual freeing done in meta_workspace_remove() for now */ +} + +static void +meta_workspace_class_init (MetaWorkspaceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_workspace_finalize; +} + +static void +meta_workspace_init (MetaWorkspace *workspace) +{ +} + static void maybe_add_to_list (MetaScreen *screen, MetaWindow *window, gpointer data) { @@ -59,7 +80,7 @@ meta_workspace_new (MetaScreen *screen) { MetaWorkspace *workspace; - workspace = g_new (MetaWorkspace, 1); + workspace = g_object_new (META_TYPE_WORKSPACE, NULL); workspace->screen = screen; workspace->screen->workspaces = @@ -112,7 +133,7 @@ workspace_free_struts (MetaWorkspace *workspace) } void -meta_workspace_free (MetaWorkspace *workspace) +meta_workspace_remove (MetaWorkspace *workspace) { GList *tmp; MetaScreen *screen; @@ -168,7 +189,7 @@ meta_workspace_free (MetaWorkspace *workspace) meta_rectangle_free_list_and_elements (workspace->xinerama_edges); } - g_free (workspace); + g_object_unref (workspace); /* don't bother to reset names, pagers can just ignore * extra ones diff --git a/src/include/display.h b/src/include/display.h index f2112529d..691f0a2c1 100644 --- a/src/include/display.h +++ b/src/include/display.h @@ -22,11 +22,22 @@ #ifndef META_DISPLAY_H #define META_DISPLAY_H -#include +#include #include #include "types.h" +typedef struct _MetaDisplayClass MetaDisplayClass; + +#define META_TYPE_DISPLAY (meta_display_get_type ()) +#define META_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), META_TYPE_DISPLAY, MetaDisplay)) +#define META_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DISPLAY, MetaDisplayClass)) +#define META_IS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), META_TYPE_DISPLAY)) +#define META_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DISPLAY)) +#define META_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DISPLAY, MetaDisplayClass)) + +GType meta_display_get_type (void) G_GNUC_CONST; + #define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0) typedef enum diff --git a/src/include/mutter-plugin.h b/src/include/mutter-plugin.h index e85760dc6..a0547f9a5 100644 --- a/src/include/mutter-plugin.h +++ b/src/include/mutter-plugin.h @@ -33,20 +33,8 @@ #include /* - * This file defines the plugin API. - * - * Effects plugin is shared library loaded via g_module_open(); it is - * recommended that the GModule API is used (otherwise you are on your own to - * do proper plugin clean up when the module is unloaded). - * - * The plugin interface is exported via the MutterPlugin struct. - */ - -typedef struct MutterPlugin MutterPlugin; - -/* - * Effect flags: identify events that the plugin can handle, used by kill_effect - * function. + * FIXME -- move these to a private include + * Required by plugin manager. */ #define MUTTER_PLUGIN_MINIMIZE (1<<0) #define MUTTER_PLUGIN_MAXIMIZE (1<<1) @@ -57,19 +45,96 @@ typedef struct MutterPlugin MutterPlugin; #define MUTTER_PLUGIN_ALL_EFFECTS (~0) -#define MUTTER_DECLARE_PLUGIN() G_MODULE_EXPORT MutterPlugin mutter_plugin = \ - { \ - METACITY_MAJOR_VERSION, \ - METACITY_MINOR_VERSION, \ - METACITY_MICRO_VERSION, \ - METACITY_CLUTTER_PLUGIN_API_VERSION \ - }; \ - static inline MutterPlugin * mutter_get_plugin () \ - { \ - return &mutter_plugin; \ - } +#define MUTTER_TYPE_PLUGIN (mutter_plugin_get_type ()) +#define MUTTER_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_PLUGIN, MutterPlugin)) +#define MUTTER_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_PLUGIN, MutterPluginClass)) +#define MUTTER_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_PLUGIN_TYPE)) +#define MUTTER_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_PLUGIN)) +#define MUTTER_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_PLUGIN, MutterPluginClass)) -struct MutterPlugin +typedef struct _MutterPlugin MutterPlugin; +typedef struct _MutterPluginClass MutterPluginClass; +typedef struct _MutterPluginVersion MutterPluginVersion; +typedef struct _MutterPluginInfo MutterPluginInfo; +typedef struct _MutterPluginPrivate MutterPluginPrivate; + +struct _MutterPlugin +{ + GObject parent; + + MutterPluginPrivate *priv; +}; + +struct _MutterPluginClass +{ + GObjectClass parent_class; + + void (*minimize) (MutterPlugin *plugin, + MutterWindow *actor); + + void (*maximize) (MutterPlugin *plugin, + MutterWindow *actor, + gint x, + gint y, + gint width, + gint height); + + void (*unmaximize) (MutterPlugin *plugin, + MutterWindow *actor, + gint x, + gint y, + gint width, + gint height); + + void (*map) (MutterPlugin *plugin, + MutterWindow *actor); + + void (*destroy) (MutterPlugin *plugin, + MutterWindow *actor); + + void (*switch_workspace) (MutterPlugin *plugin, + const GList **actors, + gint from, + gint to, + MetaMotionDirection direction); + + /* + * Called if an effect should be killed prematurely; the plugin must + * call the completed() callback as if the effect terminated naturally. + * The events parameter is a bitmask indicating which effects are to be + * killed. + */ + void (*kill_effect) (MutterPlugin *plugin, + MutterWindow *actor, + gulong events); + + /* General XEvent filter. This is fired *before* metacity itself handles + * an event. Return TRUE to block any further processing. + */ + gboolean (*xevent_filter) (MutterPlugin *plugin, + XEvent *event); + + const MutterPluginInfo * (*plugin_info) (MutterPlugin *plugin); +}; + +struct _MutterPluginInfo +{ + const gchar *name; + const gchar *version; + const gchar *author; + const gchar *license; + const gchar *description; +}; + +GType mutter_plugin_get_type (void); + +gulong mutter_plugin_features (MutterPlugin *plugin); +gboolean mutter_plugin_disabled (MutterPlugin *plugin); +gboolean mutter_plugin_running (MutterPlugin *plugin); +gboolean mutter_plugin_debug_mode (MutterPlugin *plugin); +const MutterPluginInfo * mutter_plugin_get_info (MutterPlugin *plugin); + +struct _MutterPluginVersion { /* * Version information; the first three numbers match the Metacity version @@ -83,134 +148,81 @@ struct MutterPlugin /* * Version of the plugin API; this is unrelated to the matacity version * per se. The API version is checked by the plugin manager and must match - * the one used by it (see clutter-plugins/simple.c for sample code). + * the one used by it (see clutter-plugins/default.c for sample code). */ guint version_api; - -#ifndef MUTTER_BUILDING_PLUGIN - const -#endif - gchar *name; /* Human-readable name for UI */ - - /* - * This function is called once the plugin has been loaded. - * - * @params is a string containing additional parameters for the plugin and is - * specified after the plugin name in the gconf database, separated by a - * colon. - * - * The following parameter tokens need to be handled by all - * plugins: - * - * 'debug' - * Indicates running in debug mode; the plugin - * might want to print useful debug info, or - * extend effect duration, etc. - * - * 'disable: ...;' - * - * The disable token indicates that the effects - * listed after the colon should be disabled. - * - * The list is comma-separated, terminated by a - * semicolon and consisting of the following - * tokens: - * - * minimize - * maximize - * unmaximize - * map - * destroy - * switch-workspace - * - * FIXME: ^^^ Instead of configuring in terms of what should be - * disabled, and needing a mechanism for coping with the user - * mistakenly not disabling the right things, it might be neater - * if plugins were enabled on a per effect basis in the first - * place. I.e. in gconf we could have effect:plugin key value - * pairs. - */ - - gboolean (*do_init) (const char *params); - - /* - * Event handlers - * - * Plugins must not make any special assumptions about the nature of - * ClutterActor, as the implementation details can change. - * - * Plugins must restore actor properties on completion (i.e., fade effects - * must restore opacity back to the original value, scale effects scale, - * etc.). - * - * On completion, each event handler must call the manager completed() - * callback function. - */ - void (*minimize) (MutterWindow *actor); - - void (*maximize) (MutterWindow *actor, - gint x, - gint y, - gint width, - gint height); - - void (*unmaximize) (MutterWindow *actor, - gint x, - gint y, - gint width, - gint height); - - void (*map) (MutterWindow *actor); - - void (*destroy) (MutterWindow *actor); - - /* - * Each actor in the list has a workspace number attached to it using - * g_object_set_data() with key MUTTER_PLUGIN_WORKSPACE_KEY; - * workspace < 0 indicates the window is sticky (i.e., on all desktops). - * TODO: Add accessor for sticky bit in new MutterWindow structure - */ - void (*switch_workspace) (const GList **actors, - gint from, - gint to, - MetaMotionDirection direction); - - /* - * Called if an effect should be killed prematurely; the plugin must - * call the completed() callback as if the effect terminated naturally. - * The events parameter is a bitmask indicating which effects are to be - * killed. - */ - void (*kill_effect) (MutterWindow *actor, - gulong events); - - /* - * The plugin manager will call this function when module should be reloaded. - * This happens, for example, when the parameters for the plugin changed. - */ - gboolean (*reload) (const char *params); - - /* General XEvent filter. This is fired *before* metacity itself handles - * an event. Return TRUE to block any further processing. - */ - gboolean (*xevent_filter) (XEvent *event); - - /* List of PluginWorkspaceRectangles defining the geometry of individual - * workspaces. */ - GList *work_areas; - - void *plugin_private; /* Plugin private data go here; use the plugin init - * function to allocate and initialize any private - * data. - */ - - /* Private; manager private data. */ - void *manager_private; }; -#ifndef MUTTER_PLUGIN_FROM_MANAGER_ -static inline MutterPlugin *mutter_get_plugin (); -#endif +/* + * Convenience macro to set up the plugin type. Based on GEdit. + */ +#define MUTTER_PLUGIN_DECLARE(ObjectName, object_name) \ + G_MODULE_EXPORT MutterPluginVersion mutter_plugin_version = \ + { \ + METACITY_MAJOR_VERSION, \ + METACITY_MINOR_VERSION, \ + METACITY_MICRO_VERSION, \ + METACITY_CLUTTER_PLUGIN_API_VERSION \ + }; \ + \ + static GType g_define_type_id = 0; \ + \ + /* Prototypes */ \ + G_MODULE_EXPORT \ + GType object_name##_get_type (void); \ + \ + G_MODULE_EXPORT \ + GType object_name##_register_type (GTypeModule *type_module); \ + \ + G_MODULE_EXPORT \ + GType mutter_plugin_register_type (GTypeModule *type_module); \ + \ + GType \ + object_name##_get_type () \ + { \ + return g_define_type_id; \ + } \ + \ + static void object_name##_init (ObjectName *self); \ + static void object_name##_class_init (ObjectName##Class *klass); \ + static gpointer object_name##_parent_class = NULL; \ + static void object_name##_class_intern_init (gpointer klass) \ + { \ + object_name##_parent_class = g_type_class_peek_parent (klass); \ + object_name##_class_init ((ObjectName##Class *) klass); \ + } \ + \ + GType \ + object_name##_register_type (GTypeModule *type_module) \ + { \ + static const GTypeInfo our_info = \ + { \ + sizeof (ObjectName##Class), \ + NULL, /* base_init */ \ + NULL, /* base_finalize */ \ + (GClassInitFunc) object_name##_class_intern_init, \ + NULL, \ + NULL, /* class_data */ \ + sizeof (ObjectName), \ + 0, /* n_preallocs */ \ + (GInstanceInitFunc) object_name##_init \ + }; \ + \ + g_define_type_id = g_type_module_register_type (type_module, \ + MUTTER_TYPE_PLUGIN, \ + #ObjectName, \ + &our_info, \ + 0); \ + \ + \ + return g_define_type_id; \ + } \ + \ + G_MODULE_EXPORT GType \ + mutter_plugin_register_type (GTypeModule *type_module) \ + { \ + return object_name##_register_type (type_module); \ + } \ void mutter_plugin_effect_completed (MutterPlugin *plugin, diff --git a/src/include/screen.h b/src/include/screen.h index c04bc7b54..3bdcf160a 100644 --- a/src/include/screen.h +++ b/src/include/screen.h @@ -23,9 +23,20 @@ #define META_SCREEN_H #include -#include +#include #include "types.h" +#define META_TYPE_SCREEN (meta_screen_get_type ()) +#define META_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SCREEN, MetaScreen)) +#define META_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SCREEN, MetaScreenClass)) +#define META_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_SCREEN_TYPE)) +#define META_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SCREEN)) +#define META_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SCREEN, MetaScreenClass)) + +typedef struct _MetaScreenClass MetaScreenClass; + +GType meta_screen_get_type (void); + int meta_screen_get_screen_number (MetaScreen *screen); MetaDisplay *meta_screen_get_display (MetaScreen *screen); diff --git a/src/include/window.h b/src/include/window.h index f2242cf73..e43973cac 100644 --- a/src/include/window.h +++ b/src/include/window.h @@ -22,7 +22,7 @@ #ifndef META_WINDOW_H #define META_WINDOW_H -#include +#include #include #include "boxes.h" @@ -56,6 +56,17 @@ typedef enum META_MAXIMIZE_VERTICAL = 1 << 1 } MetaMaximizeFlags; +#define META_TYPE_WINDOW (meta_window_get_type ()) +#define META_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW, MetaWindow)) +#define META_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW, MetaWindowClass)) +#define META_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_WINDOW_TYPE)) +#define META_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW)) +#define META_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW, MetaWindowClass)) + +typedef struct _MetaWindowClass MetaWindowClass; + +GType meta_window_get_type (void); + MetaFrame *meta_window_get_frame (MetaWindow *window); gboolean meta_window_has_focus (MetaWindow *window); gboolean meta_window_is_shaded (MetaWindow *window); @@ -63,8 +74,8 @@ MetaRectangle *meta_window_get_rect (MetaWindow *window); MetaScreen *meta_window_get_screen (MetaWindow *window); MetaDisplay *meta_window_get_display (MetaWindow *window); Window meta_window_get_xwindow (MetaWindow *window); -MetaWindowType meta_window_get_type (MetaWindow *window); -Atom meta_window_get_type_atom (MetaWindow *window); +MetaWindowType meta_window_get_window_type (MetaWindow *window); +Atom meta_window_get_window_type_atom (MetaWindow *window); MetaWorkspace *meta_window_get_workspace (MetaWindow *window); gboolean meta_window_is_on_all_workspaces (MetaWindow *window); gboolean meta_window_is_hidden (MetaWindow *window); diff --git a/src/include/workspace.h b/src/include/workspace.h index 00497068c..45ae52157 100644 --- a/src/include/workspace.h +++ b/src/include/workspace.h @@ -53,6 +53,17 @@ typedef enum META_MOTION_DOWN_RIGHT = -8 } MetaMotionDirection; +#define META_TYPE_WORKSPACE (meta_workspace_get_type ()) +#define META_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WORKSPACE, MetaWorkspace)) +#define META_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WORKSPACE, MetaWorkspaceClass)) +#define META_IS_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_WORKSPACE_TYPE)) +#define META_IS_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WORKSPACE)) +#define META_WORKSPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WORKSPACE, MetaWorkspaceClass)) + +typedef struct _MetaWorkspaceClass MetaWorkspaceClass; + +GType meta_workspace_get_type (void); + int meta_workspace_index (MetaWorkspace *workspace); MetaScreen *meta_workspace_get_screen (MetaWorkspace *workspace); void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,