From 66a5edd31af37d1b2770d090807bd0b32867837d Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 12 Jan 2009 13:18:39 +0000 Subject: [PATCH 01/26] [mutter-shaped-texture] workaround multi-tex combine mode for RGB tfp textures It seems that with the latest intel drivers when multi-texturing using an RGB TFP texture, the texture is being setup internally as an RGBA texture, where the alpha channel is mostly 0.0 so you only see a shimmer of the window. This workaround forcibly defines the alpha channel as 1.0. Maybe there is some clutter/cogl state that is interacting with this that is being overlooked, but for now this seems to work. (Tested on i945 + DRI2) --- src/compositor/mutter/mutter-shaped-texture.c | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) mode change 100644 => 100755 src/compositor/mutter/mutter-shaped-texture.c diff --git a/src/compositor/mutter/mutter-shaped-texture.c b/src/compositor/mutter/mutter-shaped-texture.c old mode 100644 new mode 100755 index ed01e9acc..f805391d8 --- a/src/compositor/mutter/mutter-shaped-texture.c +++ b/src/compositor/mutter/mutter-shaped-texture.c @@ -365,6 +365,15 @@ mutter_shaped_texture_paint (ClutterActor *actor) GLfloat vertex_coords[8], paint_tex_coords[8]; ClutterActorBox alloc; static const ClutterColor white = { 0xff, 0xff, 0xff, 0xff }; +#if 1 /* please see comment below about workaround */ + guint depth; + GLint orig_gl_tex_env_mode; + GLint orig_gl_combine_alpha; + GLint orig_gl_src0_alpha; + GLfloat orig_gl_tex_env_color[4]; + gboolean need_to_restore_tex_env = FALSE; + const GLfloat const_alpha[4] = { 0.0, 0.0, 0.0, 1.0 }; +#endif if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) clutter_actor_realize (CLUTTER_ACTOR (stex)); @@ -430,6 +439,36 @@ mutter_shaped_texture_paint (ClutterActor *actor) &paint_gl_width, &paint_gl_height); +#if 1 + /* This was added as a workaround. It seems that with the intel drivers when + * multi-texturing using an RGB TFP texture, the texture is actually + * setup internally as an RGBA texture, where the alpha channel is mostly + * 0.0 so you only see a shimmer of the window. This workaround forcibly + * defines the alpha channel as 1.0. Maybe there is some clutter/cogl state + * that is interacting with this that is being overlooked, but for now this + * seems to work. */ + g_object_get (G_OBJECT (stex), "pixmap-depth", &depth, NULL); + if (depth == 24) + { + glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, + &orig_gl_tex_env_mode); + glGetTexEnviv (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, &orig_gl_combine_alpha); + glGetTexEnviv (GL_TEXTURE_ENV, GL_SRC0_ALPHA, &orig_gl_src0_alpha); + glGetTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, + orig_gl_tex_env_color); + need_to_restore_tex_env = TRUE; + + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT); + glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, const_alpha); + + /* Replace the RGB in the second texture with that of the first + texture */ + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + } +#endif + /* Put the mask texture in the second texture unit */ tst_active_texture (GL_TEXTURE1); tst_client_active_texture (GL_TEXTURE1); @@ -442,11 +481,33 @@ mutter_shaped_texture_paint (ClutterActor *actor) glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); +#if 1 /* see workaround notes above */ + if (depth == 24) + { + /* NOTE: This should be redundant, since we already explicitly forced an + * an alhpa value of 1.0 for texture unit 0, but this workaround only + * seems to help if we explicitly force the alpha values for both texture + * units. */ + /* XXX - we should also save/restore the values for this texture unit too + */ + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT); + glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, const_alpha); + } + else + { +#endif + /* Multiply the alpha by the alpha in the second texture */ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS); +#if 1 /* see workaround notes above */ + } +#endif + /* Replace the RGB in the second texture with that of the first texture */ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); @@ -497,6 +558,15 @@ mutter_shaped_texture_paint (ClutterActor *actor) glDisableClientState (GL_TEXTURE_COORD_ARRAY); if (color_array_was_enabled) glEnableClientState (GL_COLOR_ARRAY); +#if 1 /* see note about workaround above */ + if (need_to_restore_tex_env) + { + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, orig_gl_tex_env_mode); + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, orig_gl_combine_alpha); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, orig_gl_src0_alpha); + glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, orig_gl_tex_env_color); + } +#endif } static void From 4589d1246d29170de3602e5fd79a768d3576b886 Mon Sep 17 00:00:00 2001 From: Thomas Wood Date: Wed, 28 Jan 2009 15:43:36 +0000 Subject: [PATCH 02/26] Update to Clutter 0.9 Fixes various API breakage due to switching to Clutter 0.9. --- configure.in | 2 +- src/compositor/mutter/compositor-mutter.c | 4 - src/compositor/mutter/mutter-shaped-texture.c | 25 +- src/compositor/mutter/mutter-shaped-texture.h | 3 +- src/compositor/mutter/plugins/default.c | 255 +++++++++--------- .../mutter/tidy/tidy-texture-frame.c | 80 +++--- 6 files changed, 187 insertions(+), 182 deletions(-) diff --git a/configure.in b/configure.in index bb2e11545..db1b72ed1 100644 --- a/configure.in +++ b/configure.in @@ -302,7 +302,7 @@ if test x$have_xrender = xyes; then AC_DEFINE(HAVE_RENDER, , [Building with Render extension support]) fi -CLUTTER_PACKAGE=clutter-0.8 +CLUTTER_PACKAGE=clutter-0.9 AC_SUBST(CLUTTER_PACKAGE) if test x$have_clutter = xyes; then METACITY_PC_MODULES="$METACITY_PC_MODULES $CLUTTER_PACKAGE " diff --git a/src/compositor/mutter/compositor-mutter.c b/src/compositor/mutter/compositor-mutter.c index 65c1cd357..884df2345 100644 --- a/src/compositor/mutter/compositor-mutter.c +++ b/src/compositor/mutter/compositor-mutter.c @@ -34,11 +34,7 @@ #include #include -#include #include -#ifdef HAVE_GLX_TEXTURE_PIXMAP -#include -#endif /* HAVE_GLX_TEXTURE_PIXMAP */ #include #define SHADOW_RADIUS 8 diff --git a/src/compositor/mutter/mutter-shaped-texture.c b/src/compositor/mutter/mutter-shaped-texture.c index f805391d8..f7bc171cd 100755 --- a/src/compositor/mutter/mutter-shaped-texture.c +++ b/src/compositor/mutter/mutter-shaped-texture.c @@ -25,15 +25,12 @@ #include -#include -#include -#ifdef HAVE_GLX_TEXTURE_PIXMAP -#include -#endif /* HAVE_GLX_TEXTURE_PIXMAP */ +#include "mutter-shaped-texture.h" + +#include #include #include -#include "mutter-shaped-texture.h" static void mutter_shaped_texture_dispose (GObject *object); static void mutter_shaped_texture_finalize (GObject *object); @@ -364,7 +361,6 @@ mutter_shaped_texture_paint (ClutterActor *actor) guint paint_gl_width, paint_gl_height; GLfloat vertex_coords[8], paint_tex_coords[8]; ClutterActorBox alloc; - static const ClutterColor white = { 0xff, 0xff, 0xff, 0xff }; #if 1 /* please see comment below about workaround */ guint depth; GLint orig_gl_tex_env_mode; @@ -427,7 +423,7 @@ mutter_shaped_texture_paint (ClutterActor *actor) glDisableClientState (GL_COLOR_ARRAY); glVertexPointer (2, GL_FLOAT, 0, vertex_coords); glTexCoordPointer (2, GL_FLOAT, 0, paint_tex_coords); - cogl_color (&white); + cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); /* Put the main painting texture in the first texture unit */ glBindTexture (paint_target, paint_gl_tex); @@ -600,16 +596,17 @@ mutter_shaped_texture_pick (ClutterActor *actor, mutter_shaped_texture_ensure_mask (stex); - cogl_color (color); + cogl_set_source_color4ub (color->red, color->green, color->blue, + color->alpha); clutter_actor_get_allocation_box (actor, &alloc); /* Paint the mask rectangle in the given color */ - cogl_texture_rectangle (priv->mask_texture, - 0, 0, - CLUTTER_UNITS_TO_FIXED (alloc.x2 - alloc.x1), - CLUTTER_UNITS_TO_FIXED (alloc.y2 - alloc.y1), - 0, 0, CFX_ONE, CFX_ONE); + cogl_set_source_texture (priv->mask_texture); + cogl_rectangle_with_texture_coords (0, 0, + CLUTTER_UNITS_TO_FIXED (alloc.x2 - alloc.x1), + CLUTTER_UNITS_TO_FIXED (alloc.y2 - alloc.y1), + 0, 0, CFX_ONE, CFX_ONE); } } diff --git a/src/compositor/mutter/mutter-shaped-texture.h b/src/compositor/mutter/mutter-shaped-texture.h index 1cac287e6..7e553098d 100644 --- a/src/compositor/mutter/mutter-shaped-texture.h +++ b/src/compositor/mutter/mutter-shaped-texture.h @@ -26,8 +26,7 @@ #ifndef __MUTTER_SHAPED_TEXTURE_H__ #define __MUTTER_SHAPED_TEXTURE_H__ -#include -#include +#include #ifdef HAVE_GLX_TEXTURE_PIXMAP #include #endif /* HAVE_GLX_TEXTURE_PIXMAP */ diff --git a/src/compositor/mutter/plugins/default.c b/src/compositor/mutter/plugins/default.c index fd7fc291a..d7f664d34 100644 --- a/src/compositor/mutter/plugins/default.c +++ b/src/compositor/mutter/plugins/default.c @@ -96,12 +96,6 @@ MUTTER_PLUGIN_DECLARE(MutterDefaultPlugin, mutter_default_plugin); */ struct _MutterDefaultPluginPrivate { - ClutterEffectTemplate *destroy_effect; - ClutterEffectTemplate *minimize_effect; - ClutterEffectTemplate *maximize_effect; - ClutterEffectTemplate *map_effect; - ClutterEffectTemplate *switch_workspace_effect; - /* Valid only when switch_workspace effect is in progress */ ClutterTimeline *tml_switch_workspace1; ClutterTimeline *tml_switch_workspace2; @@ -114,16 +108,35 @@ struct _MutterDefaultPluginPrivate gboolean debug_mode : 1; }; +/* + * Per actor private data we attach to each actor. + */ +typedef struct _ActorPrivate +{ + ClutterActor *orig_parent; + + ClutterTimeline *tml_minimize; + ClutterTimeline *tml_maximize; + ClutterTimeline *tml_destroy; + ClutterTimeline *tml_map; + + gboolean is_minimized : 1; + gboolean is_maximized : 1; +} ActorPrivate; + +/* callback data for when animations complete */ +typedef struct +{ + ClutterActor *actor; + MutterPlugin *plugin; +} EffectCompleteData; + + 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); - + /* MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv; + */ G_OBJECT_CLASS (mutter_default_plugin_parent_class)->dispose (object); } @@ -189,31 +202,6 @@ mutter_default_plugin_constructed (GObject *object) 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 @@ -254,23 +242,6 @@ mutter_default_plugin_init (MutterDefaultPlugin *self) priv->info.description = "This is an example of a plugin implementation."; } - -/* - * Per actor private data we attach to each actor. - */ -typedef struct _ActorPrivate -{ - ClutterActor *orig_parent; - - ClutterTimeline *tml_minimize; - ClutterTimeline *tml_maximize; - ClutterTimeline *tml_destroy; - ClutterTimeline *tml_map; - - gboolean is_minimized : 1; - gboolean is_maximized : 1; -} ActorPrivate; - /* * Actor private data accessor */ @@ -308,7 +279,7 @@ typedef struct SwitchWorkspaceData } SwitchWorkspaceData; static void -on_switch_workspace_effect_complete (ClutterActor *group, gpointer data) +on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data) { SwitchWorkspaceData *sw_data = data; MutterPlugin *plugin = sw_data->plugin; @@ -360,6 +331,7 @@ switch_workspace (MutterPlugin *plugin, int screen_width, screen_height; MetaScreen *screen = mutter_plugin_get_screen (plugin); SwitchWorkspaceData *sw_data = g_new (SwitchWorkspaceData, 1); + ClutterAnimation *animation; sw_data->plugin = plugin; sw_data->actors = actors; @@ -435,16 +407,23 @@ switch_workspace (MutterPlugin *plugin, priv->desktop1 = workspace0; priv->desktop2 = workspace1; - priv->tml_switch_workspace2 = - clutter_effect_scale (priv->switch_workspace_effect, - workspace1, 1.0, 1.0, - on_switch_workspace_effect_complete, - (gpointer)sw_data); + animation = clutter_actor_animate (workspace0, CLUTTER_EASE_IN_SINE, + SWITCH_TIMEOUT, + "scale-x", 1.0, + "scale-y", 1.0, + NULL); + priv->tml_switch_workspace1 = clutter_animation_get_timeline (animation); + g_signal_connect (priv->tml_switch_workspace1, + "completed", + G_CALLBACK (on_switch_workspace_effect_complete), + sw_data); - priv->tml_switch_workspace1 = - clutter_effect_scale (priv->switch_workspace_effect, - workspace0, 0.0, 0.0, - NULL, NULL); + animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE, + SWITCH_TIMEOUT, + "scale-x", 0.0, + "scale-y", 0.0, + NULL); + priv->tml_switch_workspace2 = clutter_animation_get_timeline (animation); } @@ -453,30 +432,32 @@ switch_workspace (MutterPlugin *plugin, * calls the manager callback function. */ static void -on_minimize_effect_complete (ClutterActor *actor, gpointer data) +on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) { /* * Must reverse the effect of the effect; must hide it first to ensure * that the restoration will not be visible. */ - MutterPlugin *plugin = data; + MutterPlugin *plugin = data->plugin; ActorPrivate *apriv; - MutterWindow *mc_window = MUTTER_WINDOW (actor); + MutterWindow *mc_window = MUTTER_WINDOW (data->actor); - apriv = get_actor_private (MUTTER_WINDOW (actor)); + apriv = get_actor_private (MUTTER_WINDOW (data->actor)); apriv->tml_minimize = NULL; - clutter_actor_hide (actor); + clutter_actor_hide (data->actor); /* FIXME - we shouldn't assume the original scale, it should be saved * at the start of the effect */ - clutter_actor_set_scale (actor, 1.0, 1.0); - clutter_actor_move_anchor_point_from_gravity (actor, + clutter_actor_set_scale (data->actor, 1.0, 1.0); + clutter_actor_move_anchor_point_from_gravity (data->actor, CLUTTER_GRAVITY_NORTH_WEST); /* Now notify the manager that we are done with this effect */ mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MINIMIZE); + + g_free (data); } /* @@ -486,7 +467,6 @@ on_minimize_effect_complete (ClutterActor *actor, gpointer data) static void minimize (MutterPlugin *plugin, MutterWindow *mc_window) { - MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; MetaCompWindowType type; ClutterActor *actor = CLUTTER_ACTOR (mc_window); @@ -494,6 +474,8 @@ minimize (MutterPlugin *plugin, MutterWindow *mc_window) if (type == META_COMP_WINDOW_NORMAL) { + ClutterAnimation *animation; + EffectCompleteData *data = g_new0 (EffectCompleteData, 1); ActorPrivate *apriv = get_actor_private (mc_window); apriv->is_minimized = TRUE; @@ -501,13 +483,19 @@ minimize (MutterPlugin *plugin, MutterWindow *mc_window) clutter_actor_move_anchor_point_from_gravity (actor, CLUTTER_GRAVITY_CENTER); - apriv->tml_minimize = clutter_effect_scale (priv->minimize_effect, - actor, - 0.0, - 0.0, - (ClutterEffectCompleteFunc) - on_minimize_effect_complete, - plugin); + animation = clutter_actor_animate (actor, + CLUTTER_EASE_IN_SINE, + MINIMIZE_TIMEOUT, + "scale-x", 0.0, + "scale-y", 0.0, + NULL); + apriv->tml_minimize = clutter_animation_get_timeline (animation); + data->plugin = plugin; + data->actor = actor; + g_signal_connect (apriv->tml_minimize, "completed", + G_CALLBACK (on_minimize_effect_complete), + data); + } else mutter_plugin_effect_completed (plugin, mc_window, @@ -519,25 +507,27 @@ minimize (MutterPlugin *plugin, MutterWindow *mc_window) * calls the manager callback function. */ static void -on_maximize_effect_complete (ClutterActor *actor, gpointer data) +on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) { /* * Must reverse the effect of the effect. */ - MutterPlugin * plugin = data; - MutterWindow *mc_window = MUTTER_WINDOW (actor); + MutterPlugin * plugin = data->plugin; + MutterWindow *mc_window = MUTTER_WINDOW (data->actor); ActorPrivate *apriv = get_actor_private (mc_window); apriv->tml_maximize = NULL; /* FIXME - don't assume the original scale was 1.0 */ - clutter_actor_set_scale (actor, 1.0, 1.0); - clutter_actor_move_anchor_point_from_gravity (actor, + clutter_actor_set_scale (data->actor, 1.0, 1.0); + clutter_actor_move_anchor_point_from_gravity (data->actor, CLUTTER_GRAVITY_NORTH_WEST); /* Now notify the manager that we are done with this effect */ mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAXIMIZE); + + g_free (data); } /* @@ -553,7 +543,6 @@ 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); @@ -566,6 +555,8 @@ maximize (MutterPlugin *plugin, if (type == META_COMP_WINDOW_NORMAL) { + ClutterAnimation *animation; + EffectCompleteData *data = g_new0 (EffectCompleteData, 1); ActorPrivate *apriv = get_actor_private (mc_window); guint width, height; gint x, y; @@ -589,15 +580,18 @@ maximize (MutterPlugin *plugin, clutter_actor_move_anchor_point (actor, anchor_x, anchor_y); - apriv->tml_maximize = - clutter_effect_scale (priv->maximize_effect, - actor, - scale_x, - scale_y, - (ClutterEffectCompleteFunc) - on_maximize_effect_complete, - plugin); - + animation = clutter_actor_animate (actor, + CLUTTER_EASE_IN_SINE, + MAXIMIZE_TIMEOUT, + "scale-x", scale_x, + "scale-y", scale_y, + NULL); + apriv->tml_maximize = clutter_animation_get_timeline (animation); + data->plugin = plugin; + data->actor = actor; + g_signal_connect (apriv->tml_maximize, "completed", + G_CALLBACK (on_maximize_effect_complete), + data); return; } @@ -630,22 +624,24 @@ unmaximize (MutterPlugin *plugin, } static void -on_map_effect_complete (ClutterActor *actor, gpointer data) +on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) { /* * Must reverse the effect of the effect. */ - MutterPlugin *plugin = data; - MutterWindow *mc_window = MUTTER_WINDOW (actor); + MutterPlugin *plugin = data->plugin; + MutterWindow *mc_window = MUTTER_WINDOW (data->actor); ActorPrivate *apriv = get_actor_private (mc_window); apriv->tml_map = NULL; - clutter_actor_move_anchor_point_from_gravity (actor, + clutter_actor_move_anchor_point_from_gravity (data->actor, CLUTTER_GRAVITY_NORTH_WEST); /* Now notify the manager that we are done with this effect */ mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAP); + + g_free (data); } /* @@ -655,7 +651,6 @@ on_map_effect_complete (ClutterActor *actor, gpointer data) static void map (MutterPlugin *plugin, MutterWindow *mc_window) { - MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; MetaCompWindowType type; ClutterActor *actor = CLUTTER_ACTOR (mc_window); @@ -663,6 +658,8 @@ map (MutterPlugin *plugin, MutterWindow *mc_window) if (type == META_COMP_WINDOW_NORMAL) { + ClutterAnimation *animation; + EffectCompleteData *data = g_new0 (EffectCompleteData, 1); ActorPrivate *apriv = get_actor_private (mc_window); clutter_actor_move_anchor_point_from_gravity (actor, @@ -671,13 +668,18 @@ map (MutterPlugin *plugin, MutterWindow *mc_window) clutter_actor_set_scale (actor, 0.0, 0.0); clutter_actor_show (actor); - apriv->tml_map = clutter_effect_scale (priv->map_effect, - actor, - 1.0, - 1.0, - (ClutterEffectCompleteFunc) - on_map_effect_complete, - plugin); + animation = clutter_actor_animate (actor, + CLUTTER_EASE_IN_SINE, + MAP_TIMEOUT, + "scale-x", 1.0, + "scale-y", 1.0, + NULL); + apriv->tml_map = clutter_animation_get_timeline (animation); + data->actor = actor; + data->plugin = plugin; + g_signal_connect (apriv->tml_map, "completed", + G_CALLBACK (on_map_effect_complete), + data); apriv->is_minimized = FALSE; @@ -692,10 +694,10 @@ map (MutterPlugin *plugin, MutterWindow *mc_window) * further action than notifying the manager that the effect is completed. */ static void -on_destroy_effect_complete (ClutterActor *actor, gpointer data) +on_destroy_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) { - MutterPlugin *plugin = data; - MutterWindow *mc_window = MUTTER_WINDOW (actor); + MutterPlugin *plugin = data->plugin; + MutterWindow *mc_window = MUTTER_WINDOW (data->actor); ActorPrivate *apriv = get_actor_private (mc_window); apriv->tml_destroy = NULL; @@ -710,7 +712,6 @@ on_destroy_effect_complete (ClutterActor *actor, gpointer data) static void destroy (MutterPlugin *plugin, MutterWindow *mc_window) { - MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv; MetaCompWindowType type; ClutterActor *actor = CLUTTER_ACTOR (mc_window); @@ -718,18 +719,25 @@ destroy (MutterPlugin *plugin, MutterWindow *mc_window) if (type == META_COMP_WINDOW_NORMAL) { + ClutterAnimation *animation; + EffectCompleteData *data = g_new0 (EffectCompleteData, 1); ActorPrivate *apriv = get_actor_private (mc_window); clutter_actor_move_anchor_point_from_gravity (actor, CLUTTER_GRAVITY_CENTER); - apriv->tml_destroy = clutter_effect_scale (priv->destroy_effect, - actor, - 1.0, - 0.0, - (ClutterEffectCompleteFunc) - on_destroy_effect_complete, - plugin); + animation = clutter_actor_animate (actor, + CLUTTER_EASE_IN_SINE, + DESTROY_TIMEOUT, + "scale-x", 0.0, + "scale-y", 1.0, + NULL); + apriv->tml_destroy = clutter_animation_get_timeline (animation); + data->plugin = plugin; + data->actor = actor; + g_signal_connect (apriv->tml_destroy, "completed", + G_CALLBACK (on_destroy_effect_complete), + data); } else mutter_plugin_effect_completed (plugin, mc_window, @@ -740,7 +748,6 @@ static void kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event) { ActorPrivate *apriv; - ClutterActor *actor = CLUTTER_ACTOR (mc_window); if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE) { @@ -750,7 +757,7 @@ kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event) { clutter_timeline_stop (priv->tml_switch_workspace1); clutter_timeline_stop (priv->tml_switch_workspace2); - on_switch_workspace_effect_complete (priv->desktop1, priv->actors); + g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL); } if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE)) @@ -765,25 +772,25 @@ kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event) if ((event & MUTTER_PLUGIN_MINIMIZE) && apriv->tml_minimize) { clutter_timeline_stop (apriv->tml_minimize); - on_minimize_effect_complete (actor, NULL); + g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL); } if ((event & MUTTER_PLUGIN_MAXIMIZE) && apriv->tml_maximize) { clutter_timeline_stop (apriv->tml_maximize); - on_maximize_effect_complete (actor, NULL); + g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL); } if ((event & MUTTER_PLUGIN_MAP) && apriv->tml_map) { clutter_timeline_stop (apriv->tml_map); - on_map_effect_complete (actor, NULL); + g_signal_emit_by_name (apriv->tml_map, "completed", NULL); } if ((event & MUTTER_PLUGIN_DESTROY) && apriv->tml_destroy) { clutter_timeline_stop (apriv->tml_destroy); - on_destroy_effect_complete (actor, NULL); + g_signal_emit_by_name (apriv->tml_destroy, "completed", NULL); } } diff --git a/src/compositor/mutter/tidy/tidy-texture-frame.c b/src/compositor/mutter/tidy/tidy-texture-frame.c index 2b613a7b6..34a0a1b87 100644 --- a/src/compositor/mutter/tidy/tidy-texture-frame.c +++ b/src/compositor/mutter/tidy/tidy-texture-frame.c @@ -102,7 +102,7 @@ tidy_texture_frame_paint (ClutterActor *self) ty2 = CLUTTER_INT_TO_FIXED (tex_height - priv->bottom) / tex_height; col.alpha = clutter_actor_get_paint_opacity (self); - cogl_color (&col); + cogl_set_source_color4ub (col.red, col.green, col.blue, col.alpha); ex = width - priv->right; if (ex < 0) @@ -115,41 +115,42 @@ tidy_texture_frame_paint (ClutterActor *self) #define FX(x) CLUTTER_INT_TO_FIXED(x) /* top left corner */ - cogl_texture_rectangle (cogl_texture, - 0, - 0, - FX(priv->left), /* FIXME: clip if smaller */ - FX(priv->top), - 0, - 0, - tx1, - ty1); + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords (0, + 0, + FX(priv->left), /* FIXME: clip if smaller */ + FX(priv->top), + 0, + 0, + tx1, + ty1); /* top middle */ - cogl_texture_rectangle (cogl_texture, - FX(priv->left), - FX(priv->top), - FX(ex), - 0, - tx1, - 0, - tx2, - ty1); + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords (FX(priv->left), + 0, + FX(ex), + FX(priv->top), + tx1, + 0, + tx2, + ty1); /* top right */ - cogl_texture_rectangle (cogl_texture, - FX(ex), - 0, - FX(width), - FX(priv->top), - tx2, - 0, - CFX_ONE, - ty1); + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords (FX(ex), + 0, + FX(width), + FX(priv->top), + tx2, + 0, + CFX_ONE, + ty1); /* mid left */ - cogl_texture_rectangle (cogl_texture, - 0, + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords ( + 0, FX(priv->top), FX(priv->left), FX(ey), @@ -159,7 +160,8 @@ tidy_texture_frame_paint (ClutterActor *self) ty2); /* center */ - cogl_texture_rectangle (cogl_texture, + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords ( FX(priv->left), FX(priv->top), FX(ex), @@ -170,7 +172,8 @@ tidy_texture_frame_paint (ClutterActor *self) ty2); /* mid right */ - cogl_texture_rectangle (cogl_texture, + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords ( FX(ex), FX(priv->top), FX(width), @@ -179,10 +182,11 @@ tidy_texture_frame_paint (ClutterActor *self) ty1, CFX_ONE, ty2); - + /* bottom left */ - cogl_texture_rectangle (cogl_texture, - 0, + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords ( + 0, FX(ey), FX(priv->left), FX(height), @@ -192,7 +196,8 @@ tidy_texture_frame_paint (ClutterActor *self) CFX_ONE); /* bottom center */ - cogl_texture_rectangle (cogl_texture, + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords ( FX(priv->left), FX(ey), FX(ex), @@ -203,7 +208,8 @@ tidy_texture_frame_paint (ClutterActor *self) CFX_ONE); /* bottom right */ - cogl_texture_rectangle (cogl_texture, + cogl_set_source_texture (cogl_texture); + cogl_rectangle_with_texture_coords ( FX(ex), FX(ey), FX(width), From e1cc242b5210b8d79005120bd301850222e01a8d Mon Sep 17 00:00:00 2001 From: Thomas Wood Date: Thu, 29 Jan 2009 13:43:42 +0000 Subject: [PATCH 03/26] Port TextureFrame to the new materials and Clone API Update TidyTextureFrame using clutter-0-9 branch of NbtkTextureFrame --- .../mutter/tidy/tidy-texture-frame.c | 624 ++++++++++++------ .../mutter/tidy/tidy-texture-frame.h | 71 +- 2 files changed, 470 insertions(+), 225 deletions(-) diff --git a/src/compositor/mutter/tidy/tidy-texture-frame.c b/src/compositor/mutter/tidy/tidy-texture-frame.c index 34a0a1b87..e4485aafd 100644 --- a/src/compositor/mutter/tidy/tidy-texture-frame.c +++ b/src/compositor/mutter/tidy/tidy-texture-frame.c @@ -41,68 +41,161 @@ enum { PROP_0, + + PROP_PARENT_TEXTURE, + PROP_LEFT, PROP_TOP, PROP_RIGHT, PROP_BOTTOM }; -G_DEFINE_TYPE (TidyTextureFrame, - tidy_texture_frame, - CLUTTER_TYPE_CLONE_TEXTURE); +G_DEFINE_TYPE (TidyTextureFrame, tidy_texture_frame, CLUTTER_TYPE_ACTOR); -#define TIDY_TEXTURE_FRAME_GET_PRIVATE(obj) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFramePrivate)) +#define TIDY_TEXTURE_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFramePrivate)) struct _TidyTextureFramePrivate { - gint left, top, right, bottom; + ClutterTexture *parent_texture; + + gfloat left; + gfloat top; + gfloat right; + gfloat bottom; + + CoglHandle material; }; +static void +tidy_texture_frame_get_preferred_width (ClutterActor *self, + ClutterUnit for_height, + ClutterUnit *min_width_p, + ClutterUnit *natural_width_p) +{ + TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv; + + if (G_UNLIKELY (priv->parent_texture == NULL)) + { + if (min_width_p) + *min_width_p = 0; + + if (natural_width_p) + *natural_width_p = 0; + } + else + { + ClutterActorClass *klass; + + /* by directly querying the parent texture's class implementation + * we are going around any override mechanism the parent texture + * might have in place, and we ask directly for the original + * preferred width + */ + klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture); + klass->get_preferred_width (CLUTTER_ACTOR (priv->parent_texture), + for_height, + min_width_p, + natural_width_p); + } +} + +static void +tidy_texture_frame_get_preferred_height (ClutterActor *self, + ClutterUnit for_width, + ClutterUnit *min_height_p, + ClutterUnit *natural_height_p) +{ + TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv; + + if (G_UNLIKELY (priv->parent_texture == NULL)) + { + if (min_height_p) + *min_height_p = 0; + + if (natural_height_p) + *natural_height_p = 0; + } + else + { + ClutterActorClass *klass; + + /* by directly querying the parent texture's class implementation + * we are going around any override mechanism the parent texture + * might have in place, and we ask directly for the original + * preferred height + */ + klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture); + klass->get_preferred_height (CLUTTER_ACTOR (priv->parent_texture), + for_width, + min_height_p, + natural_height_p); + } +} + +static void +tidy_texture_frame_realize (ClutterActor *self) +{ + TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv; + + if (priv->material != COGL_INVALID_HANDLE) + return; + + priv->material = cogl_material_new (); + + CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED); +} + +static void +tidy_texture_frame_unrealize (ClutterActor *self) +{ + TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv; + + if (priv->material == COGL_INVALID_HANDLE) + return; + + cogl_material_unref (priv->material); + priv->material = COGL_INVALID_HANDLE; + + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); +} + static void tidy_texture_frame_paint (ClutterActor *self) { TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv; - ClutterCloneTexture *clone_texture = CLUTTER_CLONE_TEXTURE (self); - ClutterTexture *parent_texture; - guint width, height; - guint tex_width, tex_height; - guint ex, ey; - ClutterFixed tx1, ty1, tx2, ty2; - ClutterColor col = { 0xff, 0xff, 0xff, 0xff }; - CoglHandle cogl_texture; - - priv = TIDY_TEXTURE_FRAME (self)->priv; + CoglHandle cogl_texture = COGL_INVALID_HANDLE; + ClutterActorBox box = { 0, }; + gfloat width, height; + gfloat tex_width, tex_height; + gfloat ex, ey; + gfloat tx1, ty1, tx2, ty2; + guint8 opacity; /* no need to paint stuff if we don't have a texture */ - parent_texture = clutter_clone_texture_get_parent_texture (clone_texture); - if (!parent_texture) + if (G_UNLIKELY (priv->parent_texture == NULL)) return; /* parent texture may have been hidden, so need to make sure it gets * realized */ - if (!CLUTTER_ACTOR_IS_REALIZED (parent_texture)) - clutter_actor_realize (CLUTTER_ACTOR (parent_texture)); + if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture)) + clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture)); - cogl_texture = clutter_texture_get_cogl_texture (parent_texture); + cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture); if (cogl_texture == COGL_INVALID_HANDLE) return; - cogl_push_matrix (); - tex_width = cogl_texture_get_width (cogl_texture); tex_height = cogl_texture_get_height (cogl_texture); - clutter_actor_get_size (self, &width, &height); + clutter_actor_get_allocation_box (self, &box); + width = box.x2 - box.x1; + height = box.y2 - box.y1; - tx1 = CLUTTER_INT_TO_FIXED (priv->left) / tex_width; - tx2 = CLUTTER_INT_TO_FIXED (tex_width - priv->right) / tex_width; - ty1 = CLUTTER_INT_TO_FIXED (priv->top) / tex_height; - ty2 = CLUTTER_INT_TO_FIXED (tex_height - priv->bottom) / tex_height; - - col.alpha = clutter_actor_get_paint_opacity (self); - cogl_set_source_color4ub (col.red, col.green, col.blue, col.alpha); + tx1 = priv->left / tex_width; + tx2 = (tex_width - priv->right) / tex_width; + ty1 = priv->top / tex_height; + ty2 = (tex_height - priv->bottom) / tex_height; ex = width - priv->right; if (ex < 0) @@ -112,228 +205,278 @@ tidy_texture_frame_paint (ClutterActor *self) if (ey < 0) ey = priv->bottom; /* FIXME ? */ -#define FX(x) CLUTTER_INT_TO_FIXED(x) + opacity = clutter_actor_get_paint_opacity (self); + + g_assert (priv->material != COGL_INVALID_HANDLE); + + /* set the source material using the parent texture's COGL handle */ + cogl_material_set_color4ub (priv->material, 255, 255, 255, opacity); + cogl_material_set_layer (priv->material, 0, cogl_texture); + cogl_set_source (priv->material); /* top left corner */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords (0, - 0, - FX(priv->left), /* FIXME: clip if smaller */ - FX(priv->top), - 0, - 0, - tx1, - ty1); + cogl_rectangle_with_texture_coords (0, 0, priv->left, priv->top, + 0.0, 0.0, + tx1, ty1); /* top middle */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords (FX(priv->left), - 0, - FX(ex), - FX(priv->top), - tx1, - 0, - tx2, - ty1); + cogl_rectangle_with_texture_coords (priv->left, 0, ex, priv->top, + tx1, 0.0, + tx2, ty1); /* top right */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords (FX(ex), - 0, - FX(width), - FX(priv->top), - tx2, - 0, - CFX_ONE, - ty1); + cogl_rectangle_with_texture_coords (ex, 0, width, priv->top, + tx2, 0.0, + 1.0, ty1); /* mid left */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords ( - 0, - FX(priv->top), - FX(priv->left), - FX(ey), - 0, - ty1, - tx1, - ty2); + cogl_rectangle_with_texture_coords (0, priv->top, priv->left, ey, + 0.0, ty1, + tx1, ty2); /* center */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords ( - FX(priv->left), - FX(priv->top), - FX(ex), - FX(ey), - tx1, - ty1, - tx2, - ty2); + cogl_rectangle_with_texture_coords (priv->left, priv->top, ex, ey, + tx1, ty1, + tx2, ty2); /* mid right */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords ( - FX(ex), - FX(priv->top), - FX(width), - FX(ey), - tx2, - ty1, - CFX_ONE, - ty2); + cogl_rectangle_with_texture_coords (ex, priv->top, width, ey, + tx2, ty1, + 1.0, ty2); /* bottom left */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords ( - 0, - FX(ey), - FX(priv->left), - FX(height), - 0, - ty2, - tx1, - CFX_ONE); + cogl_rectangle_with_texture_coords (0, ey, priv->left, height, + 0.0, ty2, + tx1, 1.0); /* bottom center */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords ( - FX(priv->left), - FX(ey), - FX(ex), - FX(height), - tx1, - ty2, - tx2, - CFX_ONE); + cogl_rectangle_with_texture_coords (priv->left, ey, ex, height, + tx1, ty2, + tx2, 1.0); /* bottom right */ - cogl_set_source_texture (cogl_texture); - cogl_rectangle_with_texture_coords ( - FX(ex), - FX(ey), - FX(width), - FX(height), - tx2, - ty2, - CFX_ONE, - CFX_ONE); - - - cogl_pop_matrix (); + cogl_rectangle_with_texture_coords (ex, ey, width, height, + tx2, ty2, + 1.0, 1.0); } +static inline void +tidy_texture_frame_set_frame_internal (TidyTextureFrame *frame, + gfloat left, + gfloat top, + gfloat right, + gfloat bottom) +{ + TidyTextureFramePrivate *priv = frame->priv; + GObject *gobject = G_OBJECT (frame); + gboolean changed = FALSE; + + g_object_freeze_notify (gobject); + + if (priv->top != top) + { + priv->top = top; + g_object_notify (gobject, "top"); + changed = TRUE; + } + + if (priv->right != right) + { + priv->right = right; + g_object_notify (gobject, "right"); + changed = TRUE; + } + + if (priv->bottom != bottom) + { + priv->bottom = bottom; + g_object_notify (gobject, "bottom"); + changed = TRUE; + } + + if (priv->left != left) + { + priv->left = left; + g_object_notify (gobject, "left"); + changed = TRUE; + } + + if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame)) + clutter_actor_queue_redraw (CLUTTER_ACTOR (frame)); + + g_object_thaw_notify (gobject); +} static void -tidy_texture_frame_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +tidy_texture_frame_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - TidyTextureFrame *ctexture = TIDY_TEXTURE_FRAME (object); - TidyTextureFramePrivate *priv = ctexture->priv; + TidyTextureFrame *frame = TIDY_TEXTURE_FRAME (gobject); + TidyTextureFramePrivate *priv = frame->priv; switch (prop_id) { - case PROP_LEFT: - priv->left = g_value_get_int (value); + case PROP_PARENT_TEXTURE: + tidy_texture_frame_set_parent_texture (frame, + g_value_get_object (value)); break; + case PROP_TOP: - priv->top = g_value_get_int (value); + tidy_texture_frame_set_frame_internal (frame, + priv->left, + g_value_get_float (value), + priv->right, + priv->bottom); break; + case PROP_RIGHT: - priv->right = g_value_get_int (value); + tidy_texture_frame_set_frame_internal (frame, + priv->top, + g_value_get_float (value), + priv->bottom, + priv->left); break; + case PROP_BOTTOM: - priv->bottom = g_value_get_int (value); + tidy_texture_frame_set_frame_internal (frame, + priv->top, + priv->right, + g_value_get_float (value), + priv->left); break; + + case PROP_LEFT: + tidy_texture_frame_set_frame_internal (frame, + priv->top, + priv->right, + priv->bottom, + g_value_get_float (value)); + break; + default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); break; } } static void -tidy_texture_frame_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +tidy_texture_frame_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - TidyTextureFrame *ctexture = TIDY_TEXTURE_FRAME (object); - TidyTextureFramePrivate *priv = ctexture->priv; + TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv; switch (prop_id) { + case PROP_PARENT_TEXTURE: + g_value_set_object (value, priv->parent_texture); + break; + case PROP_LEFT: - g_value_set_int (value, priv->left); + g_value_set_float (value, priv->left); break; + case PROP_TOP: - g_value_set_int (value, priv->top); + g_value_set_float (value, priv->top); break; + case PROP_RIGHT: - g_value_set_int (value, priv->right); + g_value_set_float (value, priv->right); break; + case PROP_BOTTOM: - g_value_set_int (value, priv->bottom); + g_value_set_float (value, priv->bottom); break; + default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); break; } } +static void +tidy_texture_frame_dispose (GObject *gobject) +{ + TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv; + + if (priv->parent_texture) + { + g_object_unref (priv->parent_texture); + priv->parent_texture = NULL; + } + + if (priv->material) + { + cogl_material_unref (priv->material); + priv->material = COGL_INVALID_HANDLE; + } + + G_OBJECT_CLASS (tidy_texture_frame_parent_class)->dispose (gobject); +} + static void tidy_texture_frame_class_init (TidyTextureFrameClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GParamSpec *pspec; + g_type_class_add_private (gobject_class, sizeof (TidyTextureFramePrivate)); + + actor_class->get_preferred_width = + tidy_texture_frame_get_preferred_width; + actor_class->get_preferred_height = + tidy_texture_frame_get_preferred_height; + actor_class->realize = tidy_texture_frame_realize; + actor_class->unrealize = tidy_texture_frame_unrealize; actor_class->paint = tidy_texture_frame_paint; gobject_class->set_property = tidy_texture_frame_set_property; gobject_class->get_property = tidy_texture_frame_get_property; + gobject_class->dispose = tidy_texture_frame_dispose; - g_object_class_install_property - (gobject_class, - PROP_LEFT, - g_param_spec_int ("left", - "left", - "", - 0, G_MAXINT, - 0, - TIDY_PARAM_READWRITE)); + pspec = g_param_spec_object ("parent-texture", + "Parent Texture", + "The parent ClutterTexture", + CLUTTER_TYPE_TEXTURE, + TIDY_PARAM_READWRITE | + G_PARAM_CONSTRUCT); + g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec); - g_object_class_install_property - (gobject_class, - PROP_TOP, - g_param_spec_int ("top", - "top", - "", - 0, G_MAXINT, - 0, - TIDY_PARAM_READWRITE)); + pspec = g_param_spec_float ("left", + "Left", + "Left offset", + 0, G_MAXFLOAT, + 0, + TIDY_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_LEFT, pspec); - g_object_class_install_property - (gobject_class, - PROP_BOTTOM, - g_param_spec_int ("bottom", - "bottom", - "", - 0, G_MAXINT, - 0, - TIDY_PARAM_READWRITE)); + pspec = g_param_spec_float ("top", + "Top", + "Top offset", + 0, G_MAXFLOAT, + 0, + TIDY_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_TOP, pspec); - g_object_class_install_property - (gobject_class, - PROP_RIGHT, - g_param_spec_int ("right", - "right", - "", - 0, G_MAXINT, - 0, - TIDY_PARAM_READWRITE)); + pspec = g_param_spec_float ("bottom", + "Bottom", + "Bottom offset", + 0, G_MAXFLOAT, + 0, + TIDY_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_BOTTOM, pspec); - g_type_class_add_private (gobject_class, sizeof (TidyTextureFramePrivate)); + pspec = g_param_spec_float ("right", + "Right", + "Right offset", + 0, G_MAXFLOAT, + 0, + TIDY_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_RIGHT, pspec); } static void @@ -342,14 +485,33 @@ tidy_texture_frame_init (TidyTextureFrame *self) TidyTextureFramePrivate *priv; self->priv = priv = TIDY_TEXTURE_FRAME_GET_PRIVATE (self); + + priv->material = COGL_INVALID_HANDLE; } -ClutterActor * -tidy_texture_frame_new (ClutterTexture *texture, - gint left, - gint top, - gint right, - gint bottom) +/** + * tidy_texture_frame_new: + * @texture: a #ClutterTexture or %NULL + * @left: left margin preserving its content + * @top: top margin preserving its content + * @right: right margin preserving its content + * @bottom: bottom margin preserving its content + * + * A #TidyTextureFrame is a specialized texture that efficiently clones + * an area of the given @texture while keeping preserving portions of the + * same texture. + * + * A #TidyTextureFrame can be used to make a rectangular texture fit a + * given size without stretching its borders. + * + * Return value: the newly created #TidyTextureFrame + */ +ClutterActor* +tidy_texture_frame_new (ClutterTexture *texture, + gfloat left, + gfloat top, + gfloat right, + gfloat bottom) { g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL); @@ -362,3 +524,87 @@ tidy_texture_frame_new (ClutterTexture *texture, NULL); } +ClutterTexture * +tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame) +{ + g_return_val_if_fail (TIDY_IS_TEXTURE_FRAME (frame), NULL); + + return frame->priv->parent_texture; +} + +void +tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame, + ClutterTexture *texture) +{ + TidyTextureFramePrivate *priv; + gboolean was_visible; + + g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame)); + g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture)); + + priv = frame->priv; + + was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame); + + if (priv->parent_texture == texture) + return; + + if (priv->parent_texture) + { + g_object_unref (priv->parent_texture); + priv->parent_texture = NULL; + + if (was_visible) + clutter_actor_hide (CLUTTER_ACTOR (frame)); + } + + if (texture) + { + priv->parent_texture = g_object_ref (texture); + + if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture)) + clutter_actor_show (CLUTTER_ACTOR (frame)); + } + + clutter_actor_queue_relayout (CLUTTER_ACTOR (frame)); + + g_object_notify (G_OBJECT (frame), "parent-texture"); +} + +void +tidy_texture_frame_set_frame (TidyTextureFrame *frame, + gfloat top, + gfloat right, + gfloat bottom, + gfloat left) +{ + g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame)); + + tidy_texture_frame_set_frame_internal (frame, top, right, bottom, left); +} + +void +tidy_texture_frame_get_frame (TidyTextureFrame *frame, + gfloat *top, + gfloat *right, + gfloat *bottom, + gfloat *left) +{ + TidyTextureFramePrivate *priv; + + g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame)); + + priv = frame->priv; + + if (top) + *top = priv->top; + + if (right) + *right = priv->right; + + if (bottom) + *bottom = priv->bottom; + + if (left) + *left = priv->left; +} diff --git a/src/compositor/mutter/tidy/tidy-texture-frame.h b/src/compositor/mutter/tidy/tidy-texture-frame.h index e28432a2c..0c54bfea3 100644 --- a/src/compositor/mutter/tidy/tidy-texture-frame.h +++ b/src/compositor/mutter/tidy/tidy-texture-frame.h @@ -1,6 +1,7 @@ /* tidy-texture-frame.h: Expandible texture actor * - * Copyright (C) 2007 OpenedHand + * Copyright (C) 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009 Intel Corp. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,43 +26,28 @@ G_BEGIN_DECLS -#define TIDY_TYPE_TEXTURE_FRAME (tidy_texture_frame_get_type ()) +#define TIDY_TYPE_TEXTURE_FRAME (tidy_texture_frame_get_type ()) +#define TIDY_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrame)) +#define TIDY_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass)) +#define TIDY_IS_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIDY_TYPE_TEXTURE_FRAME)) +#define TIDY_IS_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIDY_TYPE_TEXTURE_FRAME)) +#define TIDY_TEXTURE_FRAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass)) -#define TIDY_TEXTURE_FRAME(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrame)) - -#define TIDY_TEXTURE_FRAME_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass)) - -#define TIDY_IS_TEXTURE_FRAME(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - TIDY_TYPE_TEXTURE_FRAME)) - -#define TIDY_IS_TEXTURE_FRAME_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - TIDY_TYPE_TEXTURE_FRAME)) - -#define TIDY_TEXTURE_FRAME_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass)) - -typedef struct _TidyTextureFrame TidyTextureFrame; -typedef struct _TidyTextureFramePrivate TidyTextureFramePrivate; -typedef struct _TidyTextureFrameClass TidyTextureFrameClass; +typedef struct _TidyTextureFrame TidyTextureFrame; +typedef struct _TidyTextureFramePrivate TidyTextureFramePrivate; +typedef struct _TidyTextureFrameClass TidyTextureFrameClass; struct _TidyTextureFrame { - ClutterCloneTexture parent; - - /*< priv >*/ + /*< private >*/ + ClutterActor parent_instance; + TidyTextureFramePrivate *priv; }; struct _TidyTextureFrameClass { - ClutterCloneTextureClass parent_class; + ClutterActorClass parent_class; /* padding for future expansion */ void (*_clutter_box_1) (void); @@ -70,13 +56,26 @@ struct _TidyTextureFrameClass void (*_clutter_box_4) (void); }; -GType tidy_texture_frame_get_type (void) G_GNUC_CONST; -ClutterActor *tidy_texture_frame_new (ClutterTexture *texture, - gint left, - gint top, - gint right, - gint bottom); - +GType tidy_texture_frame_get_type (void) G_GNUC_CONST; +ClutterActor * tidy_texture_frame_new (ClutterTexture *texture, + gfloat top, + gfloat right, + gfloat bottom, + gfloat left); +void tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame, + ClutterTexture *texture); +ClutterTexture *tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame); +void tidy_texture_frame_set_frame (TidyTextureFrame *frame, + gfloat top, + gfloat right, + gfloat bottom, + gfloat left); +void tidy_texture_frame_get_frame (TidyTextureFrame *frame, + gfloat *top, + gfloat *right, + gfloat *bottom, + gfloat *left); + G_END_DECLS #endif /* _HAVE_TIDY_TEXTURE_FRAME_H */ From b41abfd1f8c00c5edc4ca67e3464550686ebfd20 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 30 Jan 2009 11:56:58 +0000 Subject: [PATCH 04/26] [mutter-shaped-texture] Use the new material api instead of raw GL calls Now that Cogl has the material API we can use Cogl calls for multi-texturing instead of directly calling GL. The MutterShapedTexture actor keeps a handle to a material with the right combine modes for combining the texture and the shape mask. Before each paint it sets the layers of the material to be the two textures. A second material with different combine modes 1is also created if the pixmap is 24 bit to implement the workaround from commit 72da8c57. --- src/compositor/mutter/mutter-shaped-texture.c | 395 +++++------------- 1 file changed, 101 insertions(+), 294 deletions(-) diff --git a/src/compositor/mutter/mutter-shaped-texture.c b/src/compositor/mutter/mutter-shaped-texture.c index f7bc171cd..1c91c44bb 100755 --- a/src/compositor/mutter/mutter-shaped-texture.c +++ b/src/compositor/mutter/mutter-shaped-texture.c @@ -53,29 +53,15 @@ G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture, (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_SHAPED_TEXTURE, \ MutterShapedTexturePrivate)) -enum TstMultiTexSupport - { - TST_MULTI_TEX_SUPPORT_UNKNOWN = 0, - TST_MULTI_TEX_SUPPORT_YES, - TST_MULTI_TEX_SUPPORT_NO - }; - -static enum TstMultiTexSupport -tst_multi_tex_support = TST_MULTI_TEX_SUPPORT_UNKNOWN; - -typedef void (* TstActiveTextureFunc) (GLenum texture); -typedef void (* TstClientActiveTextureFunc) (GLenum texture); - -static TstActiveTextureFunc tst_active_texture; -static TstClientActiveTextureFunc tst_client_active_texture; - struct _MutterShapedTexturePrivate { CoglHandle mask_texture; + CoglHandle material; +#if 1 /* see workaround comment in mutter_shaped_texture_paint */ + CoglHandle material_workaround; +#endif guint mask_width, mask_height; - guint mask_gl_width, mask_gl_height; - GLfloat mask_tex_coords[8]; GArray *rectangles; }; @@ -111,9 +97,23 @@ static void mutter_shaped_texture_dispose (GObject *object) { MutterShapedTexture *self = (MutterShapedTexture *) object; + MutterShapedTexturePrivate *priv = self->priv; mutter_shaped_texture_dirty_mask (self); + if (priv->material != COGL_INVALID_HANDLE) + { + cogl_material_unref (priv->material); + priv->material = COGL_INVALID_HANDLE; + } +#if 1 /* see comment in mutter_shaped_texture_paint */ + if (priv->material_workaround != COGL_INVALID_HANDLE) + { + cogl_material_unref (priv->material_workaround); + priv->material_workaround = COGL_INVALID_HANDLE; + } +#endif + G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->dispose (object); } @@ -149,97 +149,12 @@ mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex) } } -static gboolean -mutter_shaped_texture_is_multi_tex_supported (void) -{ - const gchar *extensions; - GLint max_tex_units = 0; - - if (tst_multi_tex_support != TST_MULTI_TEX_SUPPORT_UNKNOWN) - return tst_multi_tex_support == TST_MULTI_TEX_SUPPORT_YES; - - extensions = (const gchar *) glGetString (GL_EXTENSIONS); - - tst_active_texture = (TstActiveTextureFunc) - cogl_get_proc_address ("glActiveTextureARB"); - tst_client_active_texture = (TstClientActiveTextureFunc) - cogl_get_proc_address ("glClientActiveTextureARB"); - - glGetIntegerv (GL_MAX_TEXTURE_UNITS, &max_tex_units); - - if (extensions - && cogl_check_extension ("GL_ARB_multitexture", extensions) - && tst_active_texture - && tst_client_active_texture - && max_tex_units > 1) - { - tst_multi_tex_support = TST_MULTI_TEX_SUPPORT_YES; - return TRUE; - } - else - { - g_warning ("multi texturing not supported"); - tst_multi_tex_support = TST_MULTI_TEX_SUPPORT_NO; - return FALSE; - } -} - -static void -mutter_shaped_texture_set_coord_array (GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat *coords) -{ - coords[0] = x1; - coords[1] = y2; - coords[2] = x2; - coords[3] = y2; - coords[4] = x1; - coords[5] = y1; - coords[6] = x2; - coords[7] = y1; -} - -static void -mutter_shaped_texture_get_gl_size (CoglHandle tex, - guint *width, - guint *height) -{ - /* glGetTexLevelParameteriv isn't supported on GL ES so we need to - calculate the size that Cogl has used */ - - /* If NPOTs textures are supported then assume the GL texture is - exactly the right size */ - if ((cogl_get_features () & COGL_FEATURE_TEXTURE_NPOT)) - { - *width = cogl_texture_get_width (tex); - *height = cogl_texture_get_height (tex); - } - /* Otherwise assume that Cogl has used the next power of two */ - else - { - guint tex_width = cogl_texture_get_width (tex); - guint tex_height = cogl_texture_get_height (tex); - guint real_width = 1; - guint real_height = 1; - - while (real_width < tex_width) - real_width <<= 1; - while (real_height < tex_height) - real_height <<= 1; - - *width = real_width; - *height = real_height; - } -} - static void mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex) { MutterShapedTexturePrivate *priv = stex->priv; CoglHandle paint_tex; guint tex_width, tex_height; - GLuint mask_gl_tex; - GLenum mask_target; paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)); @@ -322,27 +237,6 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex) priv->mask_width = tex_width; priv->mask_height = tex_height; - - cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, &mask_target); - - mutter_shaped_texture_get_gl_size (priv->mask_texture, - &priv->mask_gl_width, - &priv->mask_gl_height); - - if (mask_target == GL_TEXTURE_RECTANGLE_ARB) - mutter_shaped_texture_set_coord_array (0.0f, 0.0f, tex_width, tex_height, - priv->mask_tex_coords); - else if ((guint) priv->mask_gl_width == tex_width - && (guint) priv->mask_gl_height == tex_height) - mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f, - priv->mask_tex_coords); - else - mutter_shaped_texture_set_coord_array (0.0f, 0.0f, - tex_width - / (GLfloat) priv->mask_gl_width, - tex_height - / (GLfloat) priv->mask_gl_height, - priv->mask_tex_coords); } } @@ -353,22 +247,10 @@ mutter_shaped_texture_paint (ClutterActor *actor) MutterShapedTexturePrivate *priv = stex->priv; CoglHandle paint_tex; guint tex_width, tex_height; - GLboolean texture_was_enabled, blend_was_enabled; - GLboolean vertex_array_was_enabled, tex_coord_array_was_enabled; - GLboolean color_array_was_enabled; - GLuint paint_gl_tex, mask_gl_tex; - GLenum paint_target, mask_target; - guint paint_gl_width, paint_gl_height; - GLfloat vertex_coords[8], paint_tex_coords[8]; ClutterActorBox alloc; + CoglHandle material; #if 1 /* please see comment below about workaround */ guint depth; - GLint orig_gl_tex_env_mode; - GLint orig_gl_combine_alpha; - GLint orig_gl_src0_alpha; - GLfloat orig_gl_tex_env_color[4]; - gboolean need_to_restore_tex_env = FALSE; - const GLfloat const_alpha[4] = { 0.0, 0.0, 0.0, 1.0 }; #endif if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) @@ -382,10 +264,9 @@ mutter_shaped_texture_paint (ClutterActor *actor) if (tex_width == 0 || tex_width == 0) /* no contents yet */ return; - /* If there are no rectangles or multi-texturing isn't supported, - fallback to the regular paint method */ - if (priv->rectangles->len < 1 - || !mutter_shaped_texture_is_multi_tex_supported ()) + /* If there are no rectangles fallback to the regular paint + method */ + if (priv->rectangles->len < 1) { CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class) ->paint (actor); @@ -395,174 +276,101 @@ mutter_shaped_texture_paint (ClutterActor *actor) if (paint_tex == COGL_INVALID_HANDLE) return; - /* If the texture is sliced then the multitexturing won't work */ - if (cogl_texture_is_sliced (paint_tex)) - { - CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class) - ->paint (actor); - return; - } - mutter_shaped_texture_ensure_mask (stex); - cogl_texture_get_gl_texture (paint_tex, &paint_gl_tex, &paint_target); - cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, &mask_target); + if (priv->material == COGL_INVALID_HANDLE) + { + priv->material = cogl_material_new (); - /* We need to keep track of the some of the old state so that we - don't confuse Cogl */ - texture_was_enabled = glIsEnabled (paint_target); - blend_was_enabled = glIsEnabled (GL_BLEND); - vertex_array_was_enabled = glIsEnabled (GL_VERTEX_ARRAY); - tex_coord_array_was_enabled = glIsEnabled (GL_TEXTURE_COORD_ARRAY); - color_array_was_enabled = glIsEnabled (GL_COLOR_ARRAY); + /* Replace the RGB from layer 1 with the RGB from layer 0 */ + cogl_material_set_layer_combine_function + (priv->material, 1, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, + COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE); + cogl_material_set_layer_combine_arg_src + (priv->material, 1, 0, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, + COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS); - glEnable (paint_target); - glEnable (GL_BLEND); - glEnableClientState (GL_VERTEX_ARRAY); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glDisableClientState (GL_COLOR_ARRAY); - glVertexPointer (2, GL_FLOAT, 0, vertex_coords); - glTexCoordPointer (2, GL_FLOAT, 0, paint_tex_coords); - cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); - - /* Put the main painting texture in the first texture unit */ - glBindTexture (paint_target, paint_gl_tex); - - /* We need the actual size of the texture so that we can calculate - the right texture coordinates if NPOTs textures are not supported - and Cogl has oversized the texture */ - mutter_shaped_texture_get_gl_size (paint_tex, - &paint_gl_width, - &paint_gl_height); + /* Modulate the alpha in layer 1 with the alpha from the + previous layer */ + cogl_material_set_layer_combine_function + (priv->material, 1, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA, + COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE); + cogl_material_set_layer_combine_arg_src + (priv->material, 1, 0, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA, + COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS); + cogl_material_set_layer_combine_arg_src + (priv->material, 1, 1, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA, + COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE); + } + material = priv->material; #if 1 - /* This was added as a workaround. It seems that with the intel drivers when - * multi-texturing using an RGB TFP texture, the texture is actually - * setup internally as an RGBA texture, where the alpha channel is mostly - * 0.0 so you only see a shimmer of the window. This workaround forcibly - * defines the alpha channel as 1.0. Maybe there is some clutter/cogl state - * that is interacting with this that is being overlooked, but for now this - * seems to work. */ - g_object_get (G_OBJECT (stex), "pixmap-depth", &depth, NULL); + /* This was added as a workaround. It seems that with the intel + * drivers when multi-texturing using an RGB TFP texture, the + * texture is actually setup internally as an RGBA texture, where + * the alpha channel is mostly 0.0 so you only see a shimmer of the + * window. This workaround forcibly defines the alpha channel as + * 1.0. Maybe there is some clutter/cogl state that is interacting + * with this that is being overlooked, but for now this seems to + * work. */ + g_object_get (stex, "pixmap-depth", &depth, NULL); if (depth == 24) { - glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, - &orig_gl_tex_env_mode); - glGetTexEnviv (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, &orig_gl_combine_alpha); - glGetTexEnviv (GL_TEXTURE_ENV, GL_SRC0_ALPHA, &orig_gl_src0_alpha); - glGetTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, - orig_gl_tex_env_color); - need_to_restore_tex_env = TRUE; + if (priv->material_workaround == COGL_INVALID_HANDLE) + { + material = priv->material_workaround = cogl_material_new (); - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT); - glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, const_alpha); + /* Replace the RGB from layer 1 with the RGB from layer 0 */ + cogl_material_set_layer_combine_function + (material, 1, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, + COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE); + cogl_material_set_layer_combine_arg_src + (material, 1, 0, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, + COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS); - /* Replace the RGB in the second texture with that of the first - texture */ - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + /* Use the alpha from layer 1 modulated with the alpha from + the primary color */ + cogl_material_set_layer_combine_function + (material, 1, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA, + COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE); + cogl_material_set_layer_combine_arg_src + (material, 1, 0, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA, + COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR); + cogl_material_set_layer_combine_arg_src + (material, 1, 1, + COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA, + COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE); + } + + material = priv->material_workaround; } #endif - /* Put the mask texture in the second texture unit */ - tst_active_texture (GL_TEXTURE1); - tst_client_active_texture (GL_TEXTURE1); - glBindTexture (mask_target, mask_gl_tex); + cogl_material_set_layer (material, 0, paint_tex); + cogl_material_set_layer (material, 1, priv->mask_texture); - glEnable (mask_target); + { + CoglColor color; + cogl_color_set_from_4ub (&color, 255, 255, 255, + clutter_actor_get_paint_opacity (actor)); + cogl_material_set_color (material, &color); + } - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, 0, priv->mask_tex_coords); - - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - -#if 1 /* see workaround notes above */ - if (depth == 24) - { - /* NOTE: This should be redundant, since we already explicitly forced an - * an alhpa value of 1.0 for texture unit 0, but this workaround only - * seems to help if we explicitly force the alpha values for both texture - * units. */ - /* XXX - we should also save/restore the values for this texture unit too - */ - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT); - glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, const_alpha); - } - else - { -#endif - - /* Multiply the alpha by the alpha in the second texture */ - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS); - -#if 1 /* see workaround notes above */ - } -#endif - - /* Replace the RGB in the second texture with that of the first - texture */ - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + cogl_set_source (material); clutter_actor_get_allocation_box (actor, &alloc); - - mutter_shaped_texture_set_coord_array (0, 0, - CLUTTER_UNITS_TO_FLOAT (alloc.x2 - - alloc.x1), - CLUTTER_UNITS_TO_FLOAT (alloc.y2 - - alloc.y1), - vertex_coords); - - if (paint_target == GL_TEXTURE_RECTANGLE_ARB) - mutter_shaped_texture_set_coord_array (0.0f, 0.0f, tex_width, tex_height, - paint_tex_coords); - else if ((guint) paint_gl_width == tex_width - && (guint) paint_gl_height == tex_height) - mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f, - paint_tex_coords); - else - mutter_shaped_texture_set_coord_array (0.0f, 0.0f, - tex_width - / (GLfloat) paint_gl_width, - tex_height - / (GLfloat) paint_gl_height, - paint_tex_coords); - - glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - - /* Disable the second texture unit and coord array */ - glDisable (mask_target); - glDisableClientState (GL_TEXTURE_COORD_ARRAY); - - /* Go back to operating on the first texture unit */ - tst_active_texture (GL_TEXTURE0); - tst_client_active_texture (GL_TEXTURE0); - - /* Restore the old state */ - if (!texture_was_enabled) - glDisable (paint_target); - if (!blend_was_enabled) - glDisable (GL_BLEND); - if (!vertex_array_was_enabled) - glDisableClientState (GL_VERTEX_ARRAY); - if (!tex_coord_array_was_enabled) - glDisableClientState (GL_TEXTURE_COORD_ARRAY); - if (color_array_was_enabled) - glEnableClientState (GL_COLOR_ARRAY); -#if 1 /* see note about workaround above */ - if (need_to_restore_tex_env) - { - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, orig_gl_tex_env_mode); - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, orig_gl_combine_alpha); - glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, orig_gl_src0_alpha); - glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, orig_gl_tex_env_color); - } -#endif + cogl_rectangle (0, 0, + CLUTTER_UNITS_TO_FLOAT (alloc.x2 - alloc.x1), + CLUTTER_UNITS_TO_FLOAT (alloc.y2 - alloc.y1)); } static void @@ -573,8 +381,7 @@ mutter_shaped_texture_pick (ClutterActor *actor, MutterShapedTexturePrivate *priv = stex->priv; /* If there are no rectangles then use the regular pick */ - if (priv->rectangles->len < 1 - || !mutter_shaped_texture_is_multi_tex_supported ()) + if (priv->rectangles->len < 1) CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class) ->pick (actor, color); else if (clutter_actor_should_pick_paint (actor)) From ff5055834b661dbc1dbc981304adf57883fcbc37 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 30 Jan 2009 11:57:46 +0000 Subject: [PATCH 05/26] Pass on MapNotify events to Clutter Clutter needs to know about MapNotify events otherwise it will never make the stage visible and nothing will paint. --- src/compositor/mutter/compositor-mutter.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/compositor/mutter/compositor-mutter.c b/src/compositor/mutter/compositor-mutter.c index 884df2345..0e61a4d11 100644 --- a/src/compositor/mutter/compositor-mutter.c +++ b/src/compositor/mutter/compositor-mutter.c @@ -1672,7 +1672,8 @@ clutter_cmp_manage_screen (MetaCompositor *compositor, PointerMotionMask | PropertyChangeMask | ButtonPressMask | ButtonReleaseMask | - KeyPressMask | KeyReleaseMask; + KeyPressMask | KeyReleaseMask | + StructureNotifyMask; if (XGetWindowAttributes (xdisplay, xwin, &attr)) { @@ -1837,6 +1838,11 @@ clutter_cmp_process_event (MetaCompositor *compositor, meta_error_trap_pop (xrc->display, FALSE); + /* Clutter needs to know about MapNotify events otherwise it will + think the stage is invisible */ + if (event->type == MapNotify) + clutter_x11_handle_event (event); + /* The above handling is basically just "observing" the events, so we return * FALSE to indicate that the event should not be filtered out; if we have * GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example. From da36829f96c5efb5ee06e18029da1d96b45a4cf4 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 29 Jan 2009 14:16:01 +0000 Subject: [PATCH 06/26] Rename keybindings.h to keybindings-private.h --- src/core/display.c | 2 +- src/core/frame.c | 2 +- src/core/{keybindings.h => keybindings-private.h} | 0 src/core/keybindings.c | 2 +- src/core/screen.c | 2 +- src/core/window.c | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename src/core/{keybindings.h => keybindings-private.h} (100%) diff --git a/src/core/display.c b/src/core/display.c index 5bad68a36..98eaf8b96 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -40,7 +40,7 @@ #include "group-props.h" #include "frame-private.h" #include "errors.h" -#include "keybindings.h" +#include "keybindings-private.h" #include "prefs.h" #include "resizepopup.h" #include "xprops.h" diff --git a/src/core/frame.c b/src/core/frame.c index d2bf62fc2..81b6f1ba7 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -27,7 +27,7 @@ #include "frame-private.h" #include "bell.h" #include "errors.h" -#include "keybindings.h" +#include "keybindings-private.h" #ifdef HAVE_RENDER #include diff --git a/src/core/keybindings.h b/src/core/keybindings-private.h similarity index 100% rename from src/core/keybindings.h rename to src/core/keybindings-private.h diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 14f9c9c40..af060462d 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -27,7 +27,7 @@ #define _SVID_SOURCE /* for putenv() */ #include -#include "keybindings.h" +#include "keybindings-private.h" #include "workspace-private.h" #include "errors.h" #include "edge-resistance.h" diff --git a/src/core/screen.c b/src/core/screen.c index b5cc1f778..cb3aede82 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -34,7 +34,7 @@ #include "frame-private.h" #include "prefs.h" #include "workspace-private.h" -#include "keybindings.h" +#include "keybindings-private.h" #include "stack.h" #include "xprops.h" #include "compositor.h" diff --git a/src/core/window.c b/src/core/window.c index 34def49ee..5c7161a6c 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -32,7 +32,7 @@ #include "errors.h" #include "workspace-private.h" #include "stack.h" -#include "keybindings.h" +#include "keybindings-private.h" #include "ui.h" #include "place.h" #include "session.h" From e25282088b633d504bf077b42eab06f57659f7d7 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 29 Jan 2009 14:53:03 +0000 Subject: [PATCH 07/26] Expose keybindings data types; add user_data parameter the handler signature. --- src/core/display-private.h | 2 +- src/core/keybindings-private.h | 7 +- src/core/keybindings.c | 177 ++++++++++++++++++--------------- src/include/keybindings.h | 60 +++++++++++ src/include/types.h | 1 + 5 files changed, 163 insertions(+), 84 deletions(-) create mode 100644 src/include/keybindings.h diff --git a/src/core/display-private.h b/src/core/display-private.h index 1f86e3bb4..808b5229e 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -37,6 +37,7 @@ #include "common.h" #include "boxes.h" #include "display.h" +#include "keybindings-private.h" #ifdef HAVE_STARTUP_NOTIFICATION #include @@ -46,7 +47,6 @@ #include #endif -typedef struct _MetaKeyBinding MetaKeyBinding; typedef struct _MetaStack MetaStack; typedef struct _MetaUISlave MetaUISlave; diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h index 618520b40..5446f4ec0 100644 --- a/src/core/keybindings-private.h +++ b/src/core/keybindings-private.h @@ -26,11 +26,10 @@ * 02111-1307, USA. */ -#ifndef META_KEYBINDINGS_H -#define META_KEYBINDINGS_H +#ifndef META_KEYBINDINGS_PRIVATE_H +#define META_KEYBINDINGS_PRIVATE_H -#include "display-private.h" -#include "window.h" +#include "keybindings.h" void meta_display_init_keys (MetaDisplay *display); void meta_display_shutdown_keys (MetaDisplay *display); diff --git a/src/core/keybindings.c b/src/core/keybindings.c index af060462d..4f1e18b4a 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -49,12 +49,6 @@ static gboolean all_bindings_disabled = FALSE; -typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding); - /* Prototypes for handlers */ #define keybind(name, handler, param, flags, stroke, description) \ static void \ @@ -62,7 +56,8 @@ handler (MetaDisplay *display,\ MetaScreen *screen,\ MetaWindow *window,\ XEvent *event,\ - MetaKeyBinding *binding); + MetaKeyBinding *binding, \ + gpointer user_data); #include "all-keybindings.h" #undef keybind @@ -75,7 +70,8 @@ static void handle_workspace_switch (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding); + MetaKeyBinding *binding, + gpointer dummy); static gboolean process_mouse_move_resize_grab (MetaDisplay *display, MetaScreen *screen, @@ -107,28 +103,12 @@ static gboolean process_workspace_switch_grab (MetaDisplay *display, static void regrab_key_bindings (MetaDisplay *display); -typedef struct -{ - const char *name; - MetaKeyHandlerFunc func; - gint data, flags; -} MetaKeyHandler; - -struct _MetaKeyBinding -{ - const char *name; - KeySym keysym; - KeyCode keycode; - unsigned int mask; - MetaVirtualModifier modifiers; - const MetaKeyHandler *handler; -}; #define keybind(name, handler, param, flags, stroke, description) \ - { #name, handler, param, flags }, + { #name, handler, param, flags, NULL, NULL }, static const MetaKeyHandler key_handlers[] = { #include "all-keybindings.h" - { NULL, NULL, 0, 0 } + { NULL, NULL, 0, 0, NULL, NULL } }; #undef keybind @@ -1219,7 +1199,8 @@ process_event (MetaKeyBinding *bindings, (* handler->func) (display, screen, bindings[i].handler->flags & BINDING_PER_WINDOW? window: NULL, event, - &bindings[i]); + &bindings[i], + handler->user_data); return TRUE; } @@ -2234,7 +2215,8 @@ handle_switch_to_workspace (MetaDisplay *display, MetaScreen *screen, MetaWindow *event_window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { gint which = binding->handler->data; MetaWorkspace *workspace; @@ -2251,7 +2233,8 @@ handle_switch_to_workspace (MetaDisplay *display, * Note that we're the only caller of that function, so perhaps * we should merge with it. */ - handle_workspace_switch (display, screen, event_window, event, binding); + handle_workspace_switch (display, screen, event_window, event, binding, + dummy); return; } @@ -2363,7 +2346,8 @@ handle_run_command (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { gint which = binding->handler->data; const char *command; @@ -2402,7 +2386,8 @@ handle_maximize_vertically (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->has_resize_func) { @@ -2418,7 +2403,8 @@ handle_maximize_horizontally (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->has_resize_func) { @@ -2442,7 +2428,8 @@ handle_move_to_corner_backend (MetaDisplay *display, gboolean xchange, gboolean ychange, gboolean to_right, - gboolean to_bottom) + gboolean to_bottom, + gpointer dummy) { MetaRectangle work_area; MetaRectangle outer; @@ -2486,9 +2473,10 @@ handle_move_to_corner_nw (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, FALSE); + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, FALSE, dummy); } static void @@ -2496,9 +2484,10 @@ handle_move_to_corner_ne (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, FALSE); + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, FALSE, dummy); } static void @@ -2506,9 +2495,10 @@ handle_move_to_corner_sw (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, TRUE); + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, TRUE, dummy); } static void @@ -2516,9 +2506,10 @@ handle_move_to_corner_se (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, TRUE); + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, TRUE, dummy); } static void @@ -2526,9 +2517,10 @@ handle_move_to_side_n (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, FALSE); + handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, FALSE, dummy); } static void @@ -2536,9 +2528,10 @@ handle_move_to_side_s (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, TRUE); + handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, TRUE, dummy); } static void @@ -2546,9 +2539,10 @@ handle_move_to_side_e (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, TRUE, FALSE); + handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, TRUE, FALSE, dummy); } static void @@ -2556,9 +2550,10 @@ handle_move_to_side_w (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { - handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, FALSE, FALSE); + handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, FALSE, FALSE, dummy); } static void @@ -2566,7 +2561,8 @@ handle_move_to_center (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { MetaRectangle work_area; MetaRectangle outer; @@ -2714,7 +2710,8 @@ handle_show_desktop (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (screen->active_workspace->showing_desktop) { @@ -2732,7 +2729,8 @@ handle_panel (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { MetaKeyBindingAction action = binding->handler->data; Atom action_atom; @@ -2783,7 +2781,8 @@ handle_activate_window_menu (MetaDisplay *display, MetaScreen *screen, MetaWindow *event_window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (display->focus_window) { @@ -2942,7 +2941,8 @@ handle_switch (MetaDisplay *display, MetaScreen *screen, MetaWindow *event_window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { gint backwards = binding->handler->flags & BINDING_IS_REVERSED; @@ -2955,7 +2955,8 @@ handle_cycle (MetaDisplay *display, MetaScreen *screen, MetaWindow *event_window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { gint backwards = binding->handler->flags & BINDING_IS_REVERSED; @@ -2969,7 +2970,8 @@ handle_toggle_fullscreen (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->fullscreen) meta_window_unmake_fullscreen (window); @@ -2982,7 +2984,8 @@ handle_toggle_above (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->wm_state_above) meta_window_unmake_above (window); @@ -2995,7 +2998,8 @@ handle_toggle_maximized (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (META_WINDOW_MAXIMIZED (window)) meta_window_unmaximize (window, @@ -3012,7 +3016,8 @@ handle_maximize (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->has_maximize_func) meta_window_maximize (window, @@ -3025,7 +3030,8 @@ handle_unmaximize (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->maximized_vertically || window->maximized_horizontally) meta_window_unmaximize (window, @@ -3038,7 +3044,8 @@ handle_toggle_shaded (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->shaded) meta_window_unshade (window, event->xkey.time); @@ -3051,7 +3058,8 @@ handle_close (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->has_close_func) meta_window_delete (window, event->xkey.time); @@ -3062,7 +3070,8 @@ handle_minimize (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->has_minimize_func) meta_window_minimize (window); @@ -3073,7 +3082,8 @@ handle_begin_move (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->has_move_func) { @@ -3089,7 +3099,8 @@ handle_begin_resize (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->has_resize_func) { @@ -3105,7 +3116,8 @@ handle_toggle_on_all_workspaces (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { if (window->on_all_workspaces) meta_window_unstick (window); @@ -3115,10 +3127,11 @@ handle_toggle_on_all_workspaces (MetaDisplay *display, static void handle_move_to_workspace (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding, + gpointer dummy) { gint which = binding->handler->data; gboolean flip = (which < 0); @@ -3172,7 +3185,8 @@ handle_raise_or_lower (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { /* Get window at pointer */ @@ -3218,7 +3232,8 @@ handle_raise (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { meta_window_raise (window); } @@ -3228,7 +3243,8 @@ handle_lower (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { meta_window_lower (window); } @@ -3238,7 +3254,8 @@ handle_workspace_switch (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { gint motion = binding->handler->data; unsigned int grab_mask; @@ -3297,10 +3314,11 @@ handle_workspace_switch (MetaDisplay *display, static void handle_set_spew_mark (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding, + gpointer dummy) { meta_verbose ("-- MARK MARK MARK MARK --\n"); } @@ -3318,7 +3336,8 @@ handle_run_terminal (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, XEvent *event, - MetaKeyBinding *binding) + MetaKeyBinding *binding, + gpointer dummy) { const char *command; GError *err; diff --git a/src/include/keybindings.h b/src/include/keybindings.h new file mode 100644 index 000000000..4009fb817 --- /dev/null +++ b/src/include/keybindings.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 Intel Corporation. + * + * 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 META_KEYBINDINGS_H +#define META_KEYBINDINGS_H + +#include "display.h" +#include "common.h" + +typedef void (* MetaKeyHandlerDataFreeFunc) (gpointer user_data); + +typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding, + gpointer user_data); + +typedef struct +{ + const char *name; + MetaKeyHandlerFunc func; + gint data, flags; + gpointer user_data; + MetaKeyHandlerDataFreeFunc user_data_free_func; +} MetaKeyHandler; + +struct _MetaKeyBinding +{ + const char *name; + KeySym keysym; + KeyCode keycode; + unsigned int mask; + MetaVirtualModifier modifiers; + const MetaKeyHandler *handler; +}; + + +void +meta_keybindings_set_custom_hander (const gchar *name, + MetaKeyHandlerFunc handler, + gpointer user_data, + MetaKeyHandlerDataFreeFunc free_data); +#endif diff --git a/src/include/types.h b/src/include/types.h index 05a091a7b..3fc60c9ee 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -29,5 +29,6 @@ typedef struct _MetaScreen MetaScreen; typedef struct _MetaWindow MetaWindow; typedef struct _MetaWorkspace MetaWorkspace; typedef struct _MetaGroup MetaGroup; +typedef struct _MetaKeyBinding MetaKeyBinding; #endif From 096e3dee8fbd9e5da93e52d420892a1eae496c06 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 29 Jan 2009 15:07:57 +0000 Subject: [PATCH 08/26] Implemented meta_keybindings_set_custom_handler(). --- src/core/keybindings.c | 49 ++++++++++++++++++++++++++++++++++----- src/include/keybindings.h | 9 ++++--- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 4f1e18b4a..0769d0b2c 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -3127,9 +3127,9 @@ handle_toggle_on_all_workspaces (MetaDisplay *display, static void handle_move_to_workspace (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, MetaKeyBinding *binding, gpointer dummy) { @@ -3314,9 +3314,9 @@ handle_workspace_switch (MetaDisplay *display, static void handle_set_spew_mark (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, MetaKeyBinding *binding, gpointer dummy) { @@ -3368,3 +3368,40 @@ handle_run_terminal (MetaDisplay *display, g_error_free (err); } } + +gboolean +meta_keybindings_set_custom_handler (const gchar *name, + MetaKeyHandlerFunc handler, + gpointer user_data, + MetaKeyHandlerDataFreeFunc free_data) +{ + MetaKeyHandler *key_handler = NULL; + guint i; + + /* + * FIXME -- the bindings should be in a hashtable or at least sorted somehow. + */ + for (i = 0; i < G_N_ELEMENTS (key_handlers); ++i) + { + if (!g_strcmp0 (key_handlers[i].name, name)) + { + key_handler = (MetaKeyHandler*)&key_handlers[i]; + break; + } + } + + if (!key_handler) + return FALSE; + + if (key_handler->user_data_free_func && key_handler->user_data) + { + key_handler->user_data_free_func (key_handler->user_data); + } + + key_handler->func = handler; + key_handler->user_data = user_data; + key_handler->user_data_free_func = free_data; + + return TRUE; +} + diff --git a/src/include/keybindings.h b/src/include/keybindings.h index 4009fb817..0ec87444c 100644 --- a/src/include/keybindings.h +++ b/src/include/keybindings.h @@ -52,9 +52,8 @@ struct _MetaKeyBinding }; -void -meta_keybindings_set_custom_hander (const gchar *name, - MetaKeyHandlerFunc handler, - gpointer user_data, - MetaKeyHandlerDataFreeFunc free_data); +gboolean meta_keybindings_set_custom_handler (const gchar *name, + MetaKeyHandlerFunc handler, + gpointer user_data, + MetaKeyHandlerDataFreeFunc free_data); #endif From b5b37d72a3ca6b679711cf3623d64e19effce94a Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 29 Jan 2009 15:14:25 +0000 Subject: [PATCH 09/26] Install keybindings.h --- src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 75690dda3..46b037ab7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +51,7 @@ metacity_SOURCES= \ core/iconcache.c \ core/iconcache.h \ core/keybindings.c \ - core/keybindings.h \ + core/keybindings-private.h \ core/main.c \ include/main.h \ core/metacity-Xatomtype.h \ @@ -160,6 +160,7 @@ libmetacityinclude_HEADERS = \ include/screen.h \ include/display.h \ include/group.h \ + include/keybindings.h \ include/mutter-plugin.h metacity_theme_viewer_SOURCES= \ From 986bdac4517fafa61cfd166bf271845dd5374493 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 29 Jan 2009 15:29:43 +0000 Subject: [PATCH 10/26] Removed const qualifier from key_handlers[] so we can modify it; use find_handler() in meta_keybindings_set_custom_handler(). --- src/core/keybindings.c | 31 ++++++++----------------------- src/include/keybindings.h | 2 +- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 0769d0b2c..932ae3217 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -106,7 +106,7 @@ static void regrab_key_bindings (MetaDisplay *display); #define keybind(name, handler, param, flags, stroke, description) \ { #name, handler, param, flags, NULL, NULL }, -static const MetaKeyHandler key_handlers[] = { +static MetaKeyHandler key_handlers[] = { #include "all-keybindings.h" { NULL, NULL, 0, 0, NULL, NULL } }; @@ -316,11 +316,11 @@ count_bindings (const MetaKeyPref *prefs, } /* FIXME: replace this with a temporary hash */ -static const MetaKeyHandler* -find_handler (const MetaKeyHandler *handlers, +static MetaKeyHandler* +find_handler (MetaKeyHandler *handlers, const char *name) { - const MetaKeyHandler *iter; + MetaKeyHandler *iter; iter = handlers; while (iter->name) @@ -360,7 +360,7 @@ rebuild_binding_table (MetaDisplay *display, if (combo && (combo->keysym != None || combo->keycode != 0)) { - const MetaKeyHandler *handler = find_handler (key_handlers, prefs[src].name); + MetaKeyHandler *handler = find_handler (key_handlers, prefs[src].name); (*bindings_p)[dest].name = prefs[src].name; (*bindings_p)[dest].handler = handler; @@ -1163,7 +1163,7 @@ process_event (MetaKeyBinding *bindings, */ for (i=0; iflags & BINDING_PER_WINDOW) || event->type != KeyPress || @@ -3375,28 +3375,13 @@ meta_keybindings_set_custom_handler (const gchar *name, gpointer user_data, MetaKeyHandlerDataFreeFunc free_data) { - MetaKeyHandler *key_handler = NULL; - guint i; - - /* - * FIXME -- the bindings should be in a hashtable or at least sorted somehow. - */ - for (i = 0; i < G_N_ELEMENTS (key_handlers); ++i) - { - if (!g_strcmp0 (key_handlers[i].name, name)) - { - key_handler = (MetaKeyHandler*)&key_handlers[i]; - break; - } - } + MetaKeyHandler *key_handler = find_handler (key_handlers, name); if (!key_handler) return FALSE; if (key_handler->user_data_free_func && key_handler->user_data) - { - key_handler->user_data_free_func (key_handler->user_data); - } + key_handler->user_data_free_func (key_handler->user_data); key_handler->func = handler; key_handler->user_data = user_data; diff --git a/src/include/keybindings.h b/src/include/keybindings.h index 0ec87444c..b2f2f4f55 100644 --- a/src/include/keybindings.h +++ b/src/include/keybindings.h @@ -48,7 +48,7 @@ struct _MetaKeyBinding KeyCode keycode; unsigned int mask; MetaVirtualModifier modifiers; - const MetaKeyHandler *handler; + MetaKeyHandler *handler; }; From b47459af580645681ea3857f022df999e7e7b78c Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 29 Jan 2009 16:26:12 +0000 Subject: [PATCH 11/26] meta_keybindings_switch_window() Public function to switch to the next window in Alt+Tab like fashion. --- src/core/keybindings.c | 13 +++++++++++++ src/include/keybindings.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 932ae3217..fb77031f3 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -3390,3 +3390,16 @@ meta_keybindings_set_custom_handler (const gchar *name, return TRUE; } +void +meta_keybindings_switch_window (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *event_window, + XEvent *event, + MetaKeyBinding *binding) +{ + gint backwards = binding->handler->flags & BINDING_IS_REVERSED; + + do_choose_window (display, screen, event_window, event, binding, + backwards, FALSE); +} + diff --git a/src/include/keybindings.h b/src/include/keybindings.h index b2f2f4f55..25ecdacfb 100644 --- a/src/include/keybindings.h +++ b/src/include/keybindings.h @@ -56,4 +56,11 @@ gboolean meta_keybindings_set_custom_handler (const gchar *name, MetaKeyHandlerFunc handler, gpointer user_data, MetaKeyHandlerDataFreeFunc free_data); + +void meta_keybindings_switch_window (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *event_window, + XEvent *event, + MetaKeyBinding *binding); + #endif From e17377d407fc83fd1f3aa7a03122e829757401f0 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Mon, 2 Feb 2009 11:00:13 +0000 Subject: [PATCH 12/26] MetaWindow::focus signal. --- src/core/window-private.h | 1 + src/core/window.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/core/window-private.h b/src/core/window-private.h index 0ab63191f..155788331 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -369,6 +369,7 @@ struct _MetaWindowClass GObjectClass parent_class; void (*workspace_changed) (MetaWindow *window, int old_workspace); + void (*focus) (MetaWindow *window); }; /* These differ from window->has_foo_func in that they consider diff --git a/src/core/window.c b/src/core/window.c index 5c7161a6c..759c7a44b 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -145,6 +145,7 @@ enum { enum { WORKSPACE_CHANGED, + FOCUS, LAST_SIGNAL }; @@ -256,6 +257,15 @@ meta_window_class_init (MetaWindowClass *klass) g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + window_signals[FOCUS] = + g_signal_new ("focus", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MetaWindowClass, focus), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -5705,6 +5715,9 @@ meta_window_notify_focus (MetaWindow *window, if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK || !meta_prefs_get_raise_on_click()) meta_display_ungrab_focus_window_button (window->display, window); + + g_signal_emit (window, window_signals[FOCUS], 0); + } } else if (event->type == FocusOut || From 1e17ba1768e559580226d004861d71336e18cfed Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Mon, 2 Feb 2009 14:08:46 +0000 Subject: [PATCH 13/26] MetaWindow::raised signal. --- src/core/window-private.h | 1 + src/core/window.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/core/window-private.h b/src/core/window-private.h index 155788331..efdb3476e 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -370,6 +370,7 @@ struct _MetaWindowClass void (*workspace_changed) (MetaWindow *window, int old_workspace); void (*focus) (MetaWindow *window); + void (*raised) (MetaWindow *window); }; /* These differ from window->has_foo_func in that they consider diff --git a/src/core/window.c b/src/core/window.c index 759c7a44b..e4d51cc62 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -146,6 +146,7 @@ enum { WORKSPACE_CHANGED, FOCUS, + RAISED, LAST_SIGNAL }; @@ -266,6 +267,15 @@ meta_window_class_init (MetaWindowClass *klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + window_signals[RAISED] = + g_signal_new ("raised", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MetaWindowClass, raised), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -4757,6 +4767,8 @@ meta_window_raise (MetaWindow *window) */ if (window != ancestor) meta_stack_raise (window->screen->stack, window); + + g_signal_emit (window, window_signals[RAISED], 0); } void From 920a847508dcd1490e9e03d3d4a67ef06defc3f4 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Mon, 2 Feb 2009 14:09:04 +0000 Subject: [PATCH 14/26] --no-tab-popup && no-tab-popup gconf key Disables the use of popup (and highlight frame) for window cycling. --- src/core/keybindings.c | 23 ++++++++++++++------- src/core/main.c | 12 +++++++++++ src/core/prefs.c | 45 ++++++++++++++++++++++++++++++++++++++++++ src/core/screen.c | 2 +- src/include/prefs.h | 4 ++++ src/ui/tabpopup.c | 23 ++++++++++++++++----- 6 files changed, 96 insertions(+), 13 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index fb77031f3..ce884847d 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -2918,16 +2918,25 @@ do_choose_window (MetaDisplay *display, } else { - meta_ui_tab_popup_select (screen->tab_popup, - (MetaTabEntryKey) initial_selection->xwindow); - - if (show_popup) - meta_ui_tab_popup_set_showing (screen->tab_popup, - TRUE); + if (!meta_prefs_get_no_tab_popup ()) + { + meta_ui_tab_popup_select (screen->tab_popup, + (MetaTabEntryKey) initial_selection->xwindow); + + if (show_popup) + meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE); + else + { + meta_window_raise (initial_selection); + initial_selection->tab_unminimized = + initial_selection->minimized; + meta_window_unminimize (initial_selection); + } + } else { meta_window_raise (initial_selection); - initial_selection->tab_unminimized = + initial_selection->tab_unminimized = initial_selection->minimized; meta_window_unminimize (initial_selection); } diff --git a/src/core/main.c b/src/core/main.c index 26ab7d459..63bb52e70 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -227,6 +227,7 @@ typedef struct gboolean sync; gboolean composite; gboolean no_composite; + gboolean no_tab_popup; } MetaArguments; #ifdef HAVE_COMPOSITE_EXTENSIONS @@ -316,6 +317,12 @@ meta_parse_options (int *argc, char ***argv, "PLUGINS" }, #endif + { + "no-tab-popup", 0, 0, G_OPTION_ARG_NONE, + &my_args.no_tab_popup, + N_("Whether window popup/frame should be shown when cycling windows."), + NULL + }, {NULL} }; GOptionContext *ctx; @@ -649,6 +656,11 @@ main (int argc, char **argv) } #endif + if (meta_args.no_tab_popup) + { + meta_prefs_override_no_tab_popup (TRUE); + } + if (!meta_display_open ()) meta_exit (META_EXIT_ERROR); diff --git a/src/core/prefs.c b/src/core/prefs.c index f62665389..555483f09 100644 --- a/src/core/prefs.c +++ b/src/core/prefs.c @@ -70,6 +70,8 @@ #define KEY_LIVE_HIDDEN_WINDOWS "/apps/metacity/general/live_hidden_windows" +#define KEY_NO_TAB_POPUP "/apps/metacity/general/no_tab_popup" + #ifdef HAVE_GCONF static GConfClient *default_client = NULL; static GList *changes = NULL; @@ -119,6 +121,8 @@ static GSList *clutter_plugins = NULL; static gboolean live_hidden_windows = FALSE; +static gboolean no_tab_popup = FALSE; + #ifdef HAVE_GCONF static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value); @@ -429,6 +433,11 @@ static MetaBoolPreference preferences_bool[] = &live_hidden_windows, FALSE, }, + { "/apps/metacity/general/no_tab_popup", + META_PREF_NO_TAB_POPUP, + &no_tab_popup, + FALSE, + }, { NULL, 0, NULL, FALSE }, }; @@ -1801,6 +1810,8 @@ meta_preference_to_string (MetaPreference pref) #endif case META_PREF_LIVE_HIDDEN_WINDOWS: return "LIVE_HIDDEN_WINDOWS"; + case META_PREF_NO_TAB_POPUP: + return "NO_TAB_POPUP"; } return "(unknown)"; @@ -2898,6 +2909,40 @@ meta_prefs_set_live_hidden_windows (gboolean whether) #endif } +gboolean +meta_prefs_get_no_tab_popup (void) +{ + return no_tab_popup; +} + +void +meta_prefs_set_no_tab_popup (gboolean whether) +{ +#ifdef HAVE_GCONF + GError *err = NULL; + + gconf_client_set_bool (default_client, + KEY_NO_TAB_POPUP, + whether, + &err); + + if (err) + { + meta_warning (_("Error setting no tab popup status: %s\n"), + err->message); + g_error_free (err); + } +#else + no_tab_popup = whether; +#endif +} + +void +meta_prefs_override_no_tab_popup (gboolean whether) +{ + no_tab_popup = whether; +} + #ifndef HAVE_GCONF static void init_button_layout(void) diff --git a/src/core/screen.c b/src/core/screen.c index cb3aede82..603c1ef74 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -1525,7 +1525,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen, screen->number, len, 5, /* FIXME */ - TRUE); + !meta_prefs_get_no_tab_popup ()); for (i = 0; i < len; i++) g_object_unref (entries[i].icon); diff --git a/src/include/prefs.h b/src/include/prefs.h index a30cd8c49..fbeb77000 100644 --- a/src/include/prefs.h +++ b/src/include/prefs.h @@ -64,6 +64,7 @@ typedef enum META_PREF_CLUTTER_PLUGINS, #endif META_PREF_LIVE_HIDDEN_WINDOWS, + META_PREF_NO_TAB_POPUP, } MetaPreference; typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, @@ -151,6 +152,9 @@ void meta_prefs_override_clutter_plugins (GSList *list); gboolean meta_prefs_get_live_hidden_windows (void); void meta_prefs_set_live_hidden_windows (gboolean whether); +gboolean meta_prefs_get_no_tab_popup (void); +void meta_prefs_set_no_tab_popup (gboolean whether); +void meta_prefs_override_no_tab_popup (gboolean whether); /* XXX FIXME This should be x-macroed, but isn't yet because it would be * difficult (or perhaps impossible) to add the suffixes using the current diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c index e8251552d..a006d9272 100644 --- a/src/ui/tabpopup.c +++ b/src/ui/tabpopup.c @@ -228,8 +228,12 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries, GdkScreen *screen; int screen_width; - popup = g_new (MetaTabPopup, 1); + popup = g_new0 (MetaTabPopup, 1); + popup->outline = outline; + + if (outline) + { popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP); screen = gdk_display_get_screen (gdk_display_get_default (), @@ -253,10 +257,6 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries, /* enable resizing, to get never-shrink behavior */ gtk_window_set_resizable (GTK_WINDOW (popup->window), TRUE); - popup->current = NULL; - popup->entries = NULL; - popup->current_selected_entry = NULL; - popup->outline = outline; screen_width = gdk_screen_get_width (screen); for (i = 0; i < entry_count; ++i) @@ -388,6 +388,16 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries, gtk_window_set_default_size (GTK_WINDOW (popup->window), max_label_width, -1); + } + else + { + for (i = 0; i < entry_count; ++i) + { + TabEntry* new_entry = + tab_entry_new (&entries[i], 0, outline); + popup->entries = g_list_prepend (popup->entries, new_entry); + } + } return popup; } @@ -413,12 +423,15 @@ meta_ui_tab_popup_free (MetaTabPopup *popup) { meta_verbose ("Destroying tab popup window\n"); + if (popup->outline) + { gtk_widget_destroy (popup->outline_window); gtk_widget_destroy (popup->window); g_list_foreach (popup->entries, free_tab_entry, NULL); g_list_free (popup->entries); + } g_free (popup); } From 5f9a4ab8ccdac3b2de647b147af1b2f26fb7a3af Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Mon, 2 Feb 2009 15:28:26 +0000 Subject: [PATCH 15/26] Do not allocate the tab_pop up object at all when the --no-tab-popup option is set This option is intended primarily so that and Alt+Tab implementation can be provided in a plugin, so having the object around makes no sense. --- src/core/keybindings.c | 31 ++++++++++--------------------- src/core/screen.c | 13 +++++++------ 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index ce884847d..230f3a9e3 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -1979,11 +1979,9 @@ process_tab_grab (MetaDisplay *display, Window prev_xwindow; MetaWindow *prev_window; - if (screen != display->grab_screen) + if (screen != display->grab_screen || !screen->tab_popup) return FALSE; - g_return_val_if_fail (screen->tab_popup != NULL, FALSE); - if (event->type == KeyRelease && end_keyboard_grab (display, event->xkey.keycode)) { @@ -2592,11 +2590,9 @@ process_workspace_switch_grab (MetaDisplay *display, { MetaWorkspace *workspace; - if (screen != display->grab_screen) + if (screen != display->grab_screen || !screen->tab_popup) return FALSE; - g_return_val_if_fail (screen->tab_popup != NULL, FALSE); - if (event->type == KeyRelease && end_keyboard_grab (display, event->xkey.keycode)) { @@ -2887,7 +2883,9 @@ do_choose_window (MetaDisplay *display, display->mouse_mode = FALSE; meta_window_activate (initial_selection, event->xkey.time); } - else if (meta_display_begin_grab_op (display, + else if (!meta_prefs_get_no_tab_popup ()) + { + if (meta_display_begin_grab_op (display, screen, NULL, show_popup ? @@ -2918,21 +2916,11 @@ do_choose_window (MetaDisplay *display, } else { - if (!meta_prefs_get_no_tab_popup ()) - { - meta_ui_tab_popup_select (screen->tab_popup, - (MetaTabEntryKey) initial_selection->xwindow); + meta_ui_tab_popup_select (screen->tab_popup, + (MetaTabEntryKey) initial_selection->xwindow); - if (show_popup) + if (show_popup) meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE); - else - { - meta_window_raise (initial_selection); - initial_selection->tab_unminimized = - initial_selection->minimized; - meta_window_unminimize (initial_selection); - } - } else { meta_window_raise (initial_selection); @@ -2943,6 +2931,7 @@ do_choose_window (MetaDisplay *display, } } } + } } static void @@ -3311,7 +3300,7 @@ handle_workspace_switch (MetaDisplay *display, meta_workspace_activate (next, event->xkey.time); - if (grabbed_before_release) + if (grabbed_before_release && !meta_prefs_get_no_tab_popup ()) { meta_ui_tab_popup_select (screen->tab_popup, (MetaTabEntryKey) next); diff --git a/src/core/screen.c b/src/core/screen.c index 603c1ef74..371bf0ab9 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -1521,11 +1521,12 @@ meta_screen_ensure_tab_popup (MetaScreen *screen, tmp = tmp->next; } - screen->tab_popup = meta_ui_tab_popup_new (entries, - screen->number, - len, - 5, /* FIXME */ - !meta_prefs_get_no_tab_popup ()); + if (!meta_prefs_get_no_tab_popup ()) + screen->tab_popup = meta_ui_tab_popup_new (entries, + screen->number, + len, + 5, /* FIXME */ + TRUE); for (i = 0; i < len; i++) g_object_unref (entries[i].icon); @@ -1547,7 +1548,7 @@ meta_screen_ensure_workspace_popup (MetaScreen *screen) int n_workspaces; int current_workspace; - if (screen->tab_popup) + if (screen->tab_popup || meta_prefs_get_no_tab_popup ()) return; current_workspace = meta_workspace_index (screen->active_workspace); From fc1ff18ca7478a9e13bc6f5fb34cd634aee03595 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Mon, 2 Feb 2009 16:53:38 +0000 Subject: [PATCH 16/26] Added meta_screen_(un)grab_all_keys() to keybindings.h. --- src/include/keybindings.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/include/keybindings.h b/src/include/keybindings.h index 25ecdacfb..abd2d7eb4 100644 --- a/src/include/keybindings.h +++ b/src/include/keybindings.h @@ -63,4 +63,7 @@ void meta_keybindings_switch_window (MetaDisplay *display, XEvent *event, MetaKeyBinding *binding); + +void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp); +gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp); #endif From d1920788ac0f579df93c5a454b6914467a625d54 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Mon, 2 Feb 2009 17:01:27 +0000 Subject: [PATCH 17/26] Move meta_display_get_tab_*() functions into display.h --- src/core/display-private.h | 30 ------------------------------ src/include/display.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/core/display-private.h b/src/core/display-private.h index 808b5229e..7b3a0696e 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -431,36 +431,6 @@ void meta_display_ping_window (MetaDisplay *display, gboolean meta_display_window_has_pending_pings (MetaDisplay *display, MetaWindow *window); -typedef enum -{ - META_TAB_LIST_NORMAL, - META_TAB_LIST_DOCKS, - META_TAB_LIST_GROUP -} MetaTabList; - -typedef enum -{ - META_TAB_SHOW_ICON, /* Alt-Tab mode */ - META_TAB_SHOW_INSTANTLY /* Alt-Esc mode */ -} MetaTabShowType; - -GList* meta_display_get_tab_list (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace); - -MetaWindow* meta_display_get_tab_next (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace, - MetaWindow *window, - gboolean backward); - -MetaWindow* meta_display_get_tab_current (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace); - int meta_resize_gravity_from_grab_op (MetaGrabOp op); gboolean meta_grab_op_is_moving (MetaGrabOp op); diff --git a/src/include/display.h b/src/include/display.h index 691f0a2c1..1775da3b1 100644 --- a/src/include/display.h +++ b/src/include/display.h @@ -27,6 +27,19 @@ #include "types.h" +typedef enum +{ + META_TAB_LIST_NORMAL, + META_TAB_LIST_DOCKS, + META_TAB_LIST_GROUP +} MetaTabList; + +typedef enum +{ + META_TAB_SHOW_ICON, /* Alt-Tab mode */ + META_TAB_SHOW_INSTANTLY /* Alt-Esc mode */ +} MetaTabShowType; + typedef struct _MetaDisplayClass MetaDisplayClass; #define META_TYPE_DISPLAY (meta_display_get_type ()) @@ -67,4 +80,20 @@ Atom meta_display_get_atom (MetaDisplay *display, MetaAtom meta_atom); guint32 meta_display_get_current_time (MetaDisplay *display); guint32 meta_display_get_current_time_roundtrip (MetaDisplay *display); +GList* meta_display_get_tab_list (MetaDisplay *display, + MetaTabList type, + MetaScreen *screen, + MetaWorkspace *workspace); + +MetaWindow* meta_display_get_tab_next (MetaDisplay *display, + MetaTabList type, + MetaScreen *screen, + MetaWorkspace *workspace, + MetaWindow *window, + gboolean backward); + +MetaWindow* meta_display_get_tab_current (MetaDisplay *display, + MetaTabList type, + MetaScreen *screen, + MetaWorkspace *workspace); #endif From f6a3ba26f99c869945691267a79c0ae9eba258da Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Tue, 3 Feb 2009 09:11:32 +0000 Subject: [PATCH 18/26] Can't g_free() MetaDisplay GObject. --- src/core/display.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/display.c b/src/core/display.c index 98eaf8b96..68b0a66eb 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -937,8 +937,7 @@ meta_display_close (MetaDisplay *display, if (display->compositor) meta_compositor_destroy (display->compositor); - g_free (display); - display = NULL; + g_object_unref (display); meta_quit (META_EXIT_SUCCESS); } From 0fdb644454471a86b2ebb1516b739768e25e7389 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 2 Feb 2009 15:16:05 -0500 Subject: [PATCH 19/26] Make compositor private a GObject than a void pointer Requiring the compositor private object to be a GObject allows the return value of meta_window_get_compositor_private() to be used via gobject-introspection, since the type and memory management can be determined. This allows a reverse mapping from MetaWindow to MutterWindow. - Change meta_window_get/set_compositor_private to use GObject rather than void * - Adapt code in compositor-mutter.c to match. --- src/compositor/mutter/compositor-mutter.c | 24 +++++++++++------------ src/core/window-private.h | 2 +- src/core/window.c | 12 ++++++++++-- src/include/window.h | 4 ++-- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/compositor/mutter/compositor-mutter.c b/src/compositor/mutter/compositor-mutter.c index 0e61a4d11..823b9e37b 100644 --- a/src/compositor/mutter/compositor-mutter.c +++ b/src/compositor/mutter/compositor-mutter.c @@ -1217,7 +1217,7 @@ add_win (MetaWindow *window) meta_verbose ("added 0x%x (%p) type:", (guint)top_window, cw); /* Hang our compositor window state off the MetaWindow for fast retrieval */ - meta_window_set_compositor_private (window, cw); + meta_window_set_compositor_private (window, G_OBJECT (cw)); /* * Add this to the list at the top of the stack before it is mapped so that @@ -1742,7 +1742,7 @@ clutter_cmp_remove_window (MetaCompositor *compositor, MutterWindow *cw = NULL; DEBUG_TRACE ("clutter_cmp_remove_window\n"); - cw = meta_window_get_compositor_private (window); + cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); if (!cw) return; @@ -1876,7 +1876,7 @@ static void clutter_cmp_map_window (MetaCompositor *compositor, MetaWindow *window) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); DEBUG_TRACE ("clutter_cmp_map_window\n"); if (!cw) return; @@ -1889,7 +1889,7 @@ static void clutter_cmp_unmap_window (MetaCompositor *compositor, MetaWindow *window) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); DEBUG_TRACE ("clutter_cmp_unmap_window\n"); if (!cw) return; @@ -1905,7 +1905,7 @@ clutter_cmp_minimize_window (MetaCompositor *compositor, MetaRectangle *icon_rect) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); MetaScreen *screen = meta_window_get_screen (window); MetaCompScreen *info = meta_screen_get_compositor_data (screen); @@ -1941,7 +1941,7 @@ clutter_cmp_unminimize_window (MetaCompositor *compositor, { #ifdef HAVE_COMPOSITE_EXTENSIONS #if 0 - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); MetaScreen *screen = meta_window_get_screen (window); MetaCompScreen *info = meta_screen_get_compositor_data (screen); @@ -1965,7 +1965,7 @@ clutter_cmp_unminimize_window (MetaCompositor *compositor, cw->priv->minimize_in_progress--; } #else - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); DEBUG_TRACE ("clutter_cmp_unminimize_window\n"); if (!cw) return; @@ -1982,7 +1982,7 @@ clutter_cmp_maximize_window (MetaCompositor *compositor, MetaRectangle *rect) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); MetaScreen *screen = meta_window_get_screen (window); MetaCompScreen *info = meta_screen_get_compositor_data (screen); @@ -2012,7 +2012,7 @@ clutter_cmp_unmaximize_window (MetaCompositor *compositor, MetaRectangle *rect) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); MetaScreen *screen = meta_window_get_screen (window); MetaCompScreen *info = meta_screen_get_compositor_data (screen); @@ -2171,7 +2171,7 @@ clutter_cmp_sync_stack (MetaCompositor *compositor, for (tmp = stack; tmp != NULL; tmp = tmp->next) { MetaWindow *window = tmp->data; - MutterWindow *cw = window->compositor_private; + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); if (!cw) { @@ -2193,7 +2193,7 @@ clutter_cmp_set_window_hidden (MetaCompositor *compositor, MetaWindow *window, gboolean hidden) { - MutterWindow *cw = window->compositor_private; + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); MetaCompScreen *info = meta_screen_get_compositor_data (screen); DEBUG_TRACE ("clutter_cmp_set_window_hidden\n"); @@ -2221,7 +2221,7 @@ clutter_cmp_sync_window_geometry (MetaCompositor *compositor, MetaWindow *window) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MutterWindow *cw = meta_window_get_compositor_private (window); + MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); MetaScreen *screen = meta_window_get_screen (window); MetaCompScreen *info = meta_screen_get_compositor_data (screen); diff --git a/src/core/window-private.h b/src/core/window-private.h index efdb3476e..5255b774b 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -360,7 +360,7 @@ struct _MetaWindow MetaGroup *group; #ifdef HAVE_COMPOSITE_EXTENSIONS - void *compositor_private; + GObject *compositor_private; #endif }; diff --git a/src/core/window.c b/src/core/window.c index e4d51cc62..a9a0d9099 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -8707,7 +8707,15 @@ meta_window_get_description (MetaWindow *window) return window->desc; } -void * +/** + * meta_window_get_compositor_private: + * @window: a #MetaWindow + * + * Gets the compositor's wrapper object for @window. + * + * Return value: (transfer none): the wrapper object. + **/ +GObject * meta_window_get_compositor_private (MetaWindow *window) { if (!window) @@ -8716,7 +8724,7 @@ meta_window_get_compositor_private (MetaWindow *window) } void -meta_window_set_compositor_private (MetaWindow *window, void *priv) +meta_window_set_compositor_private (MetaWindow *window, GObject *priv) { if (!window) return; diff --git a/src/include/window.h b/src/include/window.h index b99816dca..1ee2af647 100644 --- a/src/include/window.h +++ b/src/include/window.h @@ -92,8 +92,8 @@ void meta_window_change_workspace_by_index (MetaWindow *window, gint space_index, gboolean append, guint32 timestamp); -void *meta_window_get_compositor_private (MetaWindow *window); -void meta_window_set_compositor_private (MetaWindow *window, void *priv); +GObject *meta_window_get_compositor_private (MetaWindow *window); +void meta_window_set_compositor_private (MetaWindow *window, GObject *priv); void meta_window_configure_notify (MetaWindow *window, XConfigureEvent *event); const char *meta_window_get_role (MetaWindow *window); From 6da5a5abcb934f38359152cb526bcd281fd9a966 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Tue, 3 Feb 2009 10:15:23 +0000 Subject: [PATCH 20/26] Handle gconf errors better for string values in preferences. --- src/core/prefs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/prefs.c b/src/core/prefs.c index 555483f09..6050f8c50 100644 --- a/src/core/prefs.c +++ b/src/core/prefs.c @@ -571,7 +571,13 @@ handle_preference_init_string (void) value = gconf_client_get_string (default_client, cursor->key, &error); - cleanup_error (&error); + + if (error || !value) + { + cleanup_error (&error); + ++cursor; + continue; + } if (cursor->handler) { From f7aa5f865307cc5addb5743ab1a25732170c8290 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Tue, 3 Feb 2009 13:16:01 +0000 Subject: [PATCH 21/26] Ensure that we do not attempt to free the tab popup when there is none. --- src/core/display.c | 7 +++++-- src/ui/tabpopup.c | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/core/display.c b/src/core/display.c index 68b0a66eb..3da9651da 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -3568,8 +3568,11 @@ meta_display_end_grab_op (MetaDisplay *display, if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) || display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING) { - meta_ui_tab_popup_free (display->grab_screen->tab_popup); - display->grab_screen->tab_popup = NULL; + if (display->grab_screen->tab_popup) + { + meta_ui_tab_popup_free (display->grab_screen->tab_popup); + display->grab_screen->tab_popup = NULL; + } /* If the ungrab here causes an EnterNotify, ignore it for * sloppy focus diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c index a006d9272..d79dbee5d 100644 --- a/src/ui/tabpopup.c +++ b/src/ui/tabpopup.c @@ -422,6 +422,12 @@ void meta_ui_tab_popup_free (MetaTabPopup *popup) { meta_verbose ("Destroying tab popup window\n"); + + if (!popup) + { + meta_warning ("NULL passed to meta_ui_tab_popup_free\n"); + return; + } if (popup->outline) { From c8e967ba1cc3d847fa407667bec9ea2e4c46f509 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Tue, 3 Feb 2009 13:20:51 +0000 Subject: [PATCH 22/26] Store the default keybinding handler alongside the custom one. This allows us to fall back onto it if the custom handler removes itself. --- src/core/keybindings.c | 24 +++++++++++++++++------- src/include/keybindings.h | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 230f3a9e3..446b63e54 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -105,10 +105,10 @@ static void regrab_key_bindings (MetaDisplay *display); #define keybind(name, handler, param, flags, stroke, description) \ - { #name, handler, param, flags, NULL, NULL }, + { #name, handler, handler, param, flags, NULL, NULL }, static MetaKeyHandler key_handlers[] = { #include "all-keybindings.h" - { NULL, NULL, 0, 0, NULL, NULL } + { NULL, NULL, NULL, 0, 0, NULL, NULL } }; #undef keybind @@ -1196,11 +1196,21 @@ process_event (MetaKeyBinding *bindings, */ display->allow_terminal_deactivation = TRUE; - (* handler->func) (display, screen, - bindings[i].handler->flags & BINDING_PER_WINDOW? window: NULL, - event, - &bindings[i], - handler->user_data); + if (handler->func) + (* handler->func) (display, screen, + bindings[i].handler->flags & BINDING_PER_WINDOW ? + window: NULL, + event, + &bindings[i], + handler->user_data); + else + (* handler->default_func) (display, screen, + bindings[i].handler->flags & BINDING_PER_WINDOW ? + window: NULL, + event, + &bindings[i], + NULL); + return TRUE; } diff --git a/src/include/keybindings.h b/src/include/keybindings.h index abd2d7eb4..2619cdd83 100644 --- a/src/include/keybindings.h +++ b/src/include/keybindings.h @@ -36,6 +36,7 @@ typedef struct { const char *name; MetaKeyHandlerFunc func; + MetaKeyHandlerFunc default_func; gint data, flags; gpointer user_data; MetaKeyHandlerDataFreeFunc user_data_free_func; From 24823e19e0fe5b4d888c75b7934b78710cae0ba5 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Tue, 3 Feb 2009 13:23:08 +0000 Subject: [PATCH 23/26] Ensure that if custom handler is installed for one of the shortcuts that do keyboard grab, the custom handler gets also called while the grab is in place. --- src/core/keybindings.c | 101 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 6 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 446b63e54..bfabffe95 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -1246,7 +1246,7 @@ meta_display_process_key_event (MetaDisplay *display, event->xkey.time); if (all_bindings_disabled) return; - + /* if key event was on root window, we have a shortcut */ screen = meta_display_screen_for_root (display, event->xkey.window); @@ -1989,9 +1989,102 @@ process_tab_grab (MetaDisplay *display, Window prev_xwindow; MetaWindow *prev_window; - if (screen != display->grab_screen || !screen->tab_popup) + if (screen != display->grab_screen) return FALSE; + action = display_get_keybinding_action (display, + keysym, + event->xkey.keycode, + display->grab_mask); + + /* + * If there is no tab_pop up object, i.e., there is some custom handler + * implementing Alt+Tab & Co., we call this custom handler; we do not + * mess about with the grab, as that is up to the handler to deal with. + */ + if (!screen->tab_popup) + { + MetaKeyBinding *binding = NULL; + MetaKeyHandler *handler = NULL; + const gchar *handler_name = NULL; + gint i; + + switch (action) + { + case META_KEYBINDING_ACTION_CYCLE_PANELS: + handler_name = "cycle_group"; + break; + case META_KEYBINDING_ACTION_CYCLE_WINDOWS: + handler_name = "cycle_windows"; + break; + case META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: + handler_name = "cycle_panels_backward"; + break; + case META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: + handler_name = "cycle_windows_backward"; + break; + case META_KEYBINDING_ACTION_SWITCH_PANELS: + handler_name = "switch_panels"; + break; + case META_KEYBINDING_ACTION_SWITCH_WINDOWS: + handler_name = "switch_windows"; + break; + case META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD: + handler_name = "switch_panels_backward"; + break; + case META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD: + handler_name = "switch_windows_backward"; + break; + case META_KEYBINDING_ACTION_CYCLE_GROUP: + handler_name = "cycle_group"; + break; + case META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD: + handler_name = "cycle_group_backward"; + break; + case META_KEYBINDING_ACTION_SWITCH_GROUP: + handler_name = "switch_group"; + break; + case META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD: + handler_name = "switch_group_backward"; + break; + default: + /* + * This is the case when the Alt key is released; we preserve + * the grab, as it is up to the custom implementaiton to free it + * (a plugin can catch this in their xevent_filter function). + */ + return TRUE; + } + + handler = find_handler (key_handlers, handler_name); + + i = display->n_key_bindings - 1; + while (i >= 0) + { + if (display->key_bindings[i].keysym == keysym && + display->key_bindings[i].keycode == event->xkey.keycode && + display->key_bindings[i].mask == display->grab_mask) + { + binding = &display->key_bindings[i]; + break; + } + + --i; + } + + /* + * If we have no custom handler for this operation, we do nothing. + */ + if (!binding || !handler || + !handler->func || handler->func == handler->default_func) + return FALSE; + + (*handler->func) (display, screen, NULL, event, binding, + handler->user_data); + + return TRUE; + } + if (event->type == KeyRelease && end_keyboard_grab (display, event->xkey.keycode)) { @@ -2040,10 +2133,6 @@ process_tab_grab (MetaDisplay *display, prev_xwindow = (Window) meta_ui_tab_popup_get_selected (screen->tab_popup); prev_window = meta_display_lookup_x_window (display, prev_xwindow); - action = display_get_keybinding_action (display, - keysym, - event->xkey.keycode, - display->grab_mask); /* Cancel when alt-Escape is pressed during using alt-Tab, and vice * versa. From 17c10f60d93a89d9617fb5abaad0f8aab3ed407a Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Tue, 3 Feb 2009 17:30:49 +0000 Subject: [PATCH 24/26] Fixed process_tab_grab() When there is custom handler installed for the tab releavant tab function we do not want to actually call it form inside of this function, only to ensure that the grab is not released. The handler will get called in the normal way in process_event(). Whoever installed the handler (and requested the grab) also has to ensure the grab is released. --- src/core/keybindings.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index bfabffe95..cb9cc6306 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -2004,10 +2004,8 @@ process_tab_grab (MetaDisplay *display, */ if (!screen->tab_popup) { - MetaKeyBinding *binding = NULL; MetaKeyHandler *handler = NULL; const gchar *handler_name = NULL; - gint i; switch (action) { @@ -2056,32 +2054,16 @@ process_tab_grab (MetaDisplay *display, return TRUE; } + /* + * We do not want to actually call the handler, we just want to ensure + * that if a custom handler is installed, we do not release the grab here. + * The handler will get called as normal in the process_event() function. + */ handler = find_handler (key_handlers, handler_name); - i = display->n_key_bindings - 1; - while (i >= 0) - { - if (display->key_bindings[i].keysym == keysym && - display->key_bindings[i].keycode == event->xkey.keycode && - display->key_bindings[i].mask == display->grab_mask) - { - binding = &display->key_bindings[i]; - break; - } - - --i; - } - - /* - * If we have no custom handler for this operation, we do nothing. - */ - if (!binding || !handler || - !handler->func || handler->func == handler->default_func) + if (!handler || !handler->func || handler->func == handler->default_func) return FALSE; - (*handler->func) (display, screen, NULL, event, binding, - handler->user_data); - return TRUE; } From ee738f1d6f7dbe1f75b3ff6d4acf9613384bf706 Mon Sep 17 00:00:00 2001 From: Jonathan Matthew Date: Mon, 5 Jan 2009 20:26:47 +1000 Subject: [PATCH 25/26] Defer hiding windows until effects finish Add 'hide_after_effect' flag to MutterWindowPrivate, tracking whether the window needs to be hidden after all outstanding effects finish. Set or clear the flag as appropriate in clutter_cmp_set_window_hidden. In mutter_window_effect_completed, if hide_after_effect is TRUE and no other effects are in progress, hide the window. --- src/compositor/mutter/compositor-mutter.c | 79 +++++++++++++++-------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/src/compositor/mutter/compositor-mutter.c b/src/compositor/mutter/compositor-mutter.c index 823b9e37b..d97ba0b62 100644 --- a/src/compositor/mutter/compositor-mutter.c +++ b/src/compositor/mutter/compositor-mutter.c @@ -192,6 +192,7 @@ struct _MutterWindowPrivate guint argb32 : 1; guint disposed : 1; guint is_minimized : 1; + guint hide_after_effect : 1; /* Desktop switching flags */ guint needs_map : 1; @@ -787,6 +788,16 @@ mutter_finish_workspace_switch (MetaCompScreen *info) } +static gboolean +effect_in_progress (MutterWindow *cw, gboolean include_destroy) +{ + return (cw->priv->minimize_in_progress || + cw->priv->maximize_in_progress || + cw->priv->unmaximize_in_progress || + cw->priv->map_in_progress || + (include_destroy && cw->priv->destroy_in_progress)); +} + void mutter_window_effect_completed (MutterWindow *cw, gulong event) { @@ -794,6 +805,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); + gboolean effect_done = FALSE; /* NB: Keep in mind that when effects get completed it possible * that the corresponding MetaWindow may have be been destroyed. @@ -828,6 +840,8 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) * made visible for sake of live previews. */ clutter_actor_show (a); + + effect_done = TRUE; } } break; @@ -852,6 +866,7 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) clutter_actor_set_anchor_point (actor, 0, 0); clutter_actor_set_position (actor, rect.x, rect.y); clutter_actor_show_all (actor); + effect_done = TRUE; } break; case MUTTER_PLUGIN_DESTROY: @@ -864,7 +879,10 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) } if (!priv->destroy_in_progress) - priv->needs_destroy = TRUE; + { + priv->needs_destroy = TRUE; + effect_done = TRUE; + } break; case MUTTER_PLUGIN_UNMAXIMIZE: priv->unmaximize_in_progress--; @@ -881,6 +899,7 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) clutter_actor_set_position (actor, rect.x, rect.y); mutter_window_detach (cw); repair_win (cw); + effect_done = TRUE; } break; case MUTTER_PLUGIN_MAXIMIZE: @@ -898,6 +917,7 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) clutter_actor_set_position (actor, rect.x, rect.y); mutter_window_detach (cw); repair_win (cw); + effect_done = TRUE; } break; case MUTTER_PLUGIN_SWITCH_WORKSPACE: @@ -923,23 +943,25 @@ mutter_window_effect_completed (MutterWindow *cw, gulong event) case MUTTER_PLUGIN_DESTROY: case MUTTER_PLUGIN_UNMAXIMIZE: case MUTTER_PLUGIN_MAXIMIZE: - if (priv->needs_destroy) + + if (effect_done && + priv->hide_after_effect && + effect_in_progress (cw, TRUE) == FALSE) { - if (priv->minimize_in_progress || - priv->maximize_in_progress || - priv->unmaximize_in_progress || - priv->map_in_progress || - priv->destroy_in_progress) + if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group) { - /* wait until last effect finished */ - break; - } - else - { - clutter_actor_destroy (CLUTTER_ACTOR (cw)); - return; + clutter_actor_reparent (CLUTTER_ACTOR (cw), + info->hidden_group); } + priv->hide_after_effect = FALSE; } + + if (priv->needs_destroy && effect_in_progress (cw, TRUE) == FALSE) + { + clutter_actor_destroy (CLUTTER_ACTOR (cw)); + return; + } + default: break; } @@ -1021,10 +1043,7 @@ destroy_win (MutterWindow *cw) { priv->destroy_in_progress--; - if (priv->minimize_in_progress || - priv->maximize_in_progress || - priv->unmaximize_in_progress || - priv->map_in_progress) + if (effect_in_progress (cw, FALSE)) { priv->needs_destroy = TRUE; } @@ -1051,10 +1070,7 @@ sync_actor_position (MutterWindow *cw) priv->attrs.x = window_rect.x; priv->attrs.y = window_rect.y; - if (priv->maximize_in_progress || - priv->unmaximize_in_progress || - priv->minimize_in_progress || - priv->map_in_progress) + if (effect_in_progress (cw, FALSE)) return; clutter_actor_set_position (CLUTTER_ACTOR (cw), @@ -2194,6 +2210,7 @@ clutter_cmp_set_window_hidden (MetaCompositor *compositor, gboolean hidden) { MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window)); + MutterWindowPrivate *priv = cw->priv; MetaCompScreen *info = meta_screen_get_compositor_data (screen); DEBUG_TRACE ("clutter_cmp_set_window_hidden\n"); @@ -2202,14 +2219,22 @@ clutter_cmp_set_window_hidden (MetaCompositor *compositor, if (hidden) { - /* FIXME: There needs to be a way to queue this if there is an effect - * in progress for this window */ - if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group) - clutter_actor_reparent (CLUTTER_ACTOR (cw), - info->hidden_group); + if (effect_in_progress (cw, TRUE)) + { + priv->hide_after_effect = TRUE; + } + else + { + if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->hidden_group) + { + clutter_actor_reparent (CLUTTER_ACTOR (cw), + info->hidden_group); + } + } } else { + priv->hide_after_effect = FALSE; if (clutter_actor_get_parent (CLUTTER_ACTOR (cw)) != info->window_group) clutter_actor_reparent (CLUTTER_ACTOR (cw), info->window_group); From 3e754a6f3504ed5f0ac08d6cdab85dc660c365c5 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Fri, 6 Feb 2009 11:16:33 +0000 Subject: [PATCH 26/26] Fixed handling of _NET_WM_WINDOW_OPACITY. --- src/compositor/mutter/compositor-mutter.c | 39 ++++++++++++++++------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/compositor/mutter/compositor-mutter.c b/src/compositor/mutter/compositor-mutter.c index d97ba0b62..f9006d677 100644 --- a/src/compositor/mutter/compositor-mutter.c +++ b/src/compositor/mutter/compositor-mutter.c @@ -305,11 +305,17 @@ mutter_window_constructed (GObject *object) { MutterWindow *self = MUTTER_WINDOW (object); MutterWindowPrivate *priv = self->priv; - MetaScreen *screen = priv->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Window xwindow = priv->xwindow; - Display *xdisplay = meta_display_get_xdisplay (display); - XRenderPictFormat *format; + MetaScreen *screen = priv->screen; + MetaDisplay *display = meta_screen_get_display (screen); + Window xwindow = priv->xwindow; + Display *xdisplay = meta_display_get_xdisplay (display); + XRenderPictFormat *format; + gulong value; + Mutter *compositor; + Window xwin_child; + + compositor = (Mutter*) meta_display_get_compositor (display); + xwin_child = meta_window_get_xwindow (priv->window); mutter_window_query_window_type (self); @@ -331,11 +337,21 @@ mutter_window_constructed (GObject *object) if (format && format->type == PictTypeDirect && format->direct.alphaMask) priv->argb32 = TRUE; + if (meta_prop_get_cardinal (display, xwin_child, + compositor->atom_net_wm_window_opacity, + &value)) + { + guint8 opacity; + + opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff)); + + printf ("setting opacity to %d\n", opacity); + priv->opacity = opacity; + clutter_actor_set_opacity (CLUTTER_ACTOR (self), opacity); + } + if (mutter_window_has_shadow (self)) { - Mutter *compositor = - (Mutter*)meta_display_get_compositor (display); - priv->shadow = tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src), MAX_TILE_SZ, @@ -356,9 +372,7 @@ mutter_window_constructed (GObject *object) clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor); - update_shape ((Mutter *) - meta_display_get_compositor (display), - self); + update_shape (compositor, self); } static void @@ -1509,12 +1523,13 @@ process_property_notify (Mutter *compositor, if (meta_prop_get_cardinal (display, event->window, compositor->atom_net_wm_window_opacity, - &value) == FALSE) + &value)) { guint8 opacity; opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff)); + printf ("setting opacity to %d\n", opacity); cw->priv->opacity = opacity; clutter_actor_set_opacity (CLUTTER_ACTOR (cw), opacity); }