summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@fedoraproject.org>2009-12-10 23:33:00 +0000
committerOwen Taylor <otaylor@fedoraproject.org>2009-12-10 23:33:00 +0000
commit97b03230fda37fecb08ffb38d83e33d4c86aa7be (patch)
treef7068621f9cd94d5ccbf2672a0ec44133e8b85e7
parent2486a74f9da9245d4fe5cdf4a7cc880c49798fd5 (diff)
downloadmetacity-97b03230fda37fecb08ffb38d83e33d4c86aa7be.tar.gz
metacity-97b03230fda37fecb08ffb38d83e33d4c86aa7be.tar.xz
metacity-97b03230fda37fecb08ffb38d83e33d4c86aa7be.zip
- Require gnome-themes rather than nodoka-metacity-theme (rhbz 532455,metacity-2_28_0-13_fc13
Stijn Hoop) - Add patches for GNOME bugs 445447 - Application-induced window raise fails when raise_on_click off (rhbz 526045) 530702 - compiz doesn't start if metacity compositor is enabled (rhbz 537791) 559816 - Doesn't update keybindings being disabled/cleared (rhbz 532282) 567528 - Cannot raise windows from applications in Tcl/Tk and Java (rhbz 503522) 577576 - Failed to read saved session file warning on new sessions (rhbz 493245) 598231 - When Chromium rings the bell, metacity quits(rhbz 532282) 598995 - Don't focus ancestor window on a different workspace (rhbz 237158) 599097 - For mouse and sloppy focus, return to "mouse mode" on motion (rhbz 530261) 599248 - Add no_focus_windows preference to list windows that shouldn't be focused (rhbz 530262) 599261 - Add a new_windows_always_on_top preference (rhbz 530263) 599262 - Add XFCE Terminal as a terminal 604319 - XIOError unknown display (rhbz 537845)
-rw-r--r--Add-XFCE-Terminal-as-a-terminal.patch28
-rw-r--r--Add-a-newwindowsalwaysontop-preference.patch155
-rw-r--r--Add-nofocuswindows-preference-to-list-windows-that.patch862
-rw-r--r--Allow-applications-to-raise-windows-when-raise_on_cl.patch31
-rw-r--r--Allow-explicit-raises-from-same-client-not-just-sa.patch73
-rw-r--r--Dont-focus-ancestor-window-on-a-different-workspac.patch39
-rw-r--r--Dont-warn-about-a-missing-session-file.patch36
-rw-r--r--For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch394
-rw-r--r--cm-selection-timestamp.patch43
-rw-r--r--metacity-2.28-empty-keybindings.patch39
-rw-r--r--metacity-2.28-visual-bell.patch41
-rw-r--r--metacity-2.28-xioerror-unknown-display.patch58
-rw-r--r--metacity.spec57
13 files changed, 1854 insertions, 2 deletions
diff --git a/Add-XFCE-Terminal-as-a-terminal.patch b/Add-XFCE-Terminal-as-a-terminal.patch
new file mode 100644
index 0000000..8a544d1
--- /dev/null
+++ b/Add-XFCE-Terminal-as-a-terminal.patch
@@ -0,0 +1,28 @@
+From bf7327acb41a43b2bdeee9f0855455ebaef8b816 Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Wed, 21 Oct 2009 21:11:46 -0400
+Subject: [PATCH] Add XFCE Terminal as a terminal
+
+Include the XFCE terminal program 'Terminal' in the list of terminals.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=599262
+---
+ src/core/window.c | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/src/core/window.c b/src/core/window.c
+index 0ae6a01..b481ccf 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -1951,6 +1951,9 @@ __window_is_terminal (MetaWindow *window)
+ /* mlterm ("multi lingual terminal emulator on X") */
+ else if (strcmp (window->res_class, "mlterm") == 0)
+ return TRUE;
++ /* Terminal -- XFCE Terminal */
++ else if (strcmp (window->res_class, "Terminal") == 0)
++ return TRUE;
+
+ return FALSE;
+ }
+--
+1.6.5.rc2 \ No newline at end of file
diff --git a/Add-a-newwindowsalwaysontop-preference.patch b/Add-a-newwindowsalwaysontop-preference.patch
new file mode 100644
index 0000000..c4b26b5
--- /dev/null
+++ b/Add-a-newwindowsalwaysontop-preference.patch
@@ -0,0 +1,155 @@
+From c4fba8198bacc8ecf911cb15c9cd9314f3204a85 Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Wed, 21 Oct 2009 19:22:35 -0400
+Subject: [PATCH] Add a new_windows_always_on_top preference
+
+Add a /apps/metacity/general/new_windows_always_on_top preference.
+When set, new windows are always placed on top, even if they are
+denied focus.
+
+This is useful on large screens and multihead setups where the
+tasklist can be hard to notice and difficult to mouse to, so the
+normal behavior of flashing in the tasklist is less effective.
+---
+ src/core/prefs.c | 17 ++++++++++++++++-
+ src/core/window.c | 6 +++++-
+ src/include/prefs.h | 2 ++
+ src/metacity.schemas.in.in | 29 +++++++++++++++++++++++++++++
+ 4 files changed, 52 insertions(+), 2 deletions(-)
+
+diff --git a/src/core/prefs.c b/src/core/prefs.c
+index e03c816..1bf888b 100644
+--- a/src/core/prefs.c
++++ b/src/core/prefs.c
+@@ -79,6 +79,7 @@ static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
+ static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART;
+ static GSList *no_focus_windows = NULL;
+ static gboolean raise_on_click = TRUE;
++static gboolean new_windows_always_on_top = TRUE;
+ static char* current_theme = NULL;
+ static int num_workspaces = 4;
+ static MetaActionTitlebar action_double_click_titlebar = META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE;
+@@ -358,6 +359,11 @@ static MetaBoolPreference preferences_bool[] =
+ &raise_on_click,
+ TRUE,
+ },
++ { "/apps/metacity/general/new_windows_always_on_top",
++ META_PREF_NEW_WINDOWS_ALWAYS_ON_TOP,
++ &new_windows_always_on_top,
++ TRUE,
++ },
+ { "/apps/metacity/general/titlebar_uses_system_font",
+ META_PREF_TITLEBAR_FONT, /* note! shares a pref */
+ &use_system_font,
+@@ -1271,6 +1277,12 @@ meta_prefs_get_raise_on_click (void)
+ return raise_on_click || focus_mode == META_FOCUS_MODE_CLICK;
+ }
+
++gboolean
++meta_prefs_get_new_windows_always_on_top (void)
++{
++ return new_windows_always_on_top;
++}
++
+ const char*
+ meta_prefs_get_theme (void)
+ {
+@@ -1709,7 +1721,10 @@ meta_preference_to_string (MetaPreference pref)
+
+ case META_PREF_RAISE_ON_CLICK:
+ return "RAISE_ON_CLICK";
+-
++
++ case META_PREF_NEW_WINDOWS_ALWAYS_ON_TOP:
++ return "NEW_WINDOWS_ALWAYS_ON_TOP";
++
+ case META_PREF_THEME:
+ return "THEME";
+
+diff --git a/src/core/window.c b/src/core/window.c
+index 10da47a..0ae6a01 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -1983,7 +1983,7 @@ window_state_on_map (MetaWindow *window,
+ if (!(window->input || window->take_focus))
+ {
+ *takes_focus = FALSE;
+- return;
++ goto out;
+ }
+
+ /* Terminal usage may be different; some users intend to launch
+@@ -2030,6 +2030,10 @@ window_state_on_map (MetaWindow *window,
+ /* The default is correct for these */
+ break;
+ }
++
++ out:
++ if (meta_prefs_get_new_windows_always_on_top ())
++ *places_on_top = TRUE;
+ }
+
+ static gboolean
+diff --git a/src/include/prefs.h b/src/include/prefs.h
+index 6698dfe..8c7cd09 100644
+--- a/src/include/prefs.h
++++ b/src/include/prefs.h
+@@ -35,6 +35,7 @@ typedef enum
+ META_PREF_FOCUS_MODE,
+ META_PREF_FOCUS_NEW_WINDOWS,
+ META_PREF_RAISE_ON_CLICK,
++ META_PREF_NEW_WINDOWS_ALWAYS_ON_TOP,
+ META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
+ META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
+ META_PREF_ACTION_RIGHT_CLICK_TITLEBAR,
+@@ -81,6 +82,7 @@ guint meta_prefs_get_mouse_button_menu (void);
+ MetaFocusMode meta_prefs_get_focus_mode (void);
+ MetaFocusNewWindows meta_prefs_get_focus_new_windows (void);
+ gboolean meta_prefs_get_raise_on_click (void);
++gboolean meta_prefs_get_new_windows_always_on_top (void);
+ const char* meta_prefs_get_theme (void);
+ /* returns NULL if GTK default should be used */
+ const PangoFontDescription* meta_prefs_get_titlebar_font (void);
+diff --git a/src/metacity.schemas.in.in b/src/metacity.schemas.in.in
+index 25ca5f3..14155fa 100644
+--- a/src/metacity.schemas.in.in
++++ b/src/metacity.schemas.in.in
+@@ -166,6 +166,35 @@
+ </schema>
+
+ <schema>
++ <key>/schemas/apps/metacity/general/new_windows_always_on_top</key>
++ <applyto>/apps/metacity/general/new_windows_always_on_top</applyto>
++ <owner>metacity</owner>
++ <type>bool</type>
++ <default>false</default>
++ <locale name="C">
++ <short>Whether new windows should always be placed on top</short>
++ <long>
++ The normal behavior is that if a new window is not given the
++ focus (since, for example, the user has interacted with another
++ window after launching an application), then if the window would
++ be stacked on top of the focus window, the window is instead
++ stacked beneath and flashed in the taskbar. This behavior can
++ be annoying on large screens and multihead setups where the
++ taskbar is hard to notice and difficult to get to, so this option,
++ if set, disables this behavior, and new windows are always placed
++ on top, whether or not they get focus.
++
++ Note that if this option is set, a new window may completely hide
++ the focus window but not get focus itself, which can be quite confusing
++ to users. Also, note that setting this option breaks the normal
++ invariant in the 'click' focus mode that the topmost window always
++ has focus, so its most suitable for use with the 'mouse' and
++ 'sloppy' focus modes.
++ </long>
++ </locale>
++ </schema>
++
++ <schema>
+ <key>/schemas/apps/metacity/general/action_double_click_titlebar</key>
+ <applyto>/apps/metacity/general/action_double_click_titlebar</applyto>
+ <owner>metacity</owner>
+--
+1.6.5.rc2
+
diff --git a/Add-nofocuswindows-preference-to-list-windows-that.patch b/Add-nofocuswindows-preference-to-list-windows-that.patch
new file mode 100644
index 0000000..ddad5be
--- /dev/null
+++ b/Add-nofocuswindows-preference-to-list-windows-that.patch
@@ -0,0 +1,862 @@
+From 88c66808ec5f2bfba425fc6d6f0b9ac43ed44696 Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Wed, 21 Oct 2009 18:07:12 -0400
+Subject: [PATCH] Add no_focus_windows preference to list windows that shouldn't be focused
+
+Notification windows from legacy software that don't set _NET_WM_USER_TIME
+can be a huge annoyance for users, since they will pop up and steal focus.
+
+Add:
+
+ /apps/metacity/general/no_focus_windows
+
+which is a list of expressions identifying new windows that shouldn't ever
+be focused. For example:
+
+ (and (eq class 'Mylegacyapp') (glob name 'New mail*'))
+
+https://bugzilla.gnome.org/show_bug.cgi?id=599248
+---
+ src/Makefile.am | 2 +
+ src/core/prefs.c | 43 ++++
+ src/core/window-matcher.c | 582 ++++++++++++++++++++++++++++++++++++++++++++
+ src/core/window-matcher.h | 46 ++++
+ src/core/window.c | 9 +-
+ src/include/prefs.h | 6 +-
+ src/metacity.schemas.in.in | 28 ++
+ 7 files changed, 714 insertions(+), 2 deletions(-)
+ create mode 100644 src/core/window-matcher.c
+ create mode 100644 src/core/window-matcher.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index bd3420f..3baf422 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -65,6 +65,8 @@ metacity_SOURCES= \
+ core/stack.h \
+ core/util.c \
+ include/util.h \
++ core/window-matcher.c \
++ core/window-matcher.h \
+ core/window-props.c \
+ core/window-props.h \
+ core/window.c \
+diff --git a/src/core/prefs.c b/src/core/prefs.c
+index 6e41b3c..e03c816 100644
+--- a/src/core/prefs.c
++++ b/src/core/prefs.c
+@@ -25,6 +25,7 @@
+
+ #include <config.h>
+ #include "prefs.h"
++#include "window-matcher.h"
+ #include "ui.h"
+ #include "util.h"
+ #ifdef HAVE_GCONF
+@@ -76,6 +77,7 @@ static PangoFontDescription *titlebar_font = NULL;
+ static MetaVirtualModifier mouse_button_mods = Mod1Mask;
+ static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
+ static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART;
++static GSList *no_focus_windows = NULL;
+ static gboolean raise_on_click = TRUE;
+ static char* current_theme = NULL;
+ static int num_workspaces = 4;
+@@ -147,6 +149,7 @@ static void maybe_give_disable_workarounds_warning (void);
+
+ static void titlebar_handler (MetaPreference, const gchar*, gboolean*);
+ static void theme_name_handler (MetaPreference, const gchar*, gboolean*);
++static void no_focus_windows_handler (MetaPreference, const gchar*, gboolean*);
+ static void mouse_button_mods_handler (MetaPreference, const gchar*, gboolean*);
+ static void button_layout_handler (MetaPreference, const gchar*, gboolean*);
+
+@@ -425,6 +428,11 @@ static MetaStringPreference preferences_string[] =
+ theme_name_handler,
+ NULL,
+ },
++ { "/apps/metacity/general/no_focus_windows",
++ META_PREF_NO_FOCUS_WINDOWS,
++ no_focus_windows_handler,
++ NULL
++ },
+ { KEY_TITLEBAR_FONT,
+ META_PREF_TITLEBAR_FONT,
+ titlebar_handler,
+@@ -1344,6 +1352,30 @@ theme_name_handler (MetaPreference pref,
+ }
+
+ static void
++no_focus_windows_handler (MetaPreference pref,
++ const gchar *string_value,
++ gboolean *inform_listeners)
++{
++ if (no_focus_windows)
++ {
++ meta_window_matcher_list_free (no_focus_windows);
++ no_focus_windows = NULL;
++ }
++
++ if (string_value)
++ {
++ GError *error = NULL;
++ no_focus_windows = meta_window_matcher_list_from_string (string_value, &error);
++ if (error != NULL)
++ {
++ meta_warning ("Error parsing no_focus_windows='%s': %s\n",
++ string_value, error->message);
++ g_error_free (error);
++ }
++ }
++}
++
++static void
+ mouse_button_mods_handler (MetaPreference pref,
+ const gchar *string_value,
+ gboolean *inform_listeners)
+@@ -1755,6 +1787,9 @@ meta_preference_to_string (MetaPreference pref)
+
+ case META_PREF_FORCE_FULLSCREEN:
+ return "FORCE_FULLSCREEN";
++
++ case META_PREF_NO_FOCUS_WINDOWS:
++ return "NO_FOCUS_WINDOWS";
+ }
+
+ return "(unknown)";
+@@ -2633,6 +2668,14 @@ meta_prefs_get_action_right_click_titlebar (void)
+ }
+
+ gboolean
++meta_prefs_window_is_no_focus (const char *window_name,
++ const char *window_class)
++{
++ return meta_window_matcher_list_matches (no_focus_windows,
++ window_name, window_class);
++}
++
++gboolean
+ meta_prefs_get_auto_raise (void)
+ {
+ return auto_raise;
+diff --git a/src/core/window-matcher.c b/src/core/window-matcher.c
+new file mode 100644
+index 0000000..e2fd293
+--- /dev/null
++++ b/src/core/window-matcher.c
+@@ -0,0 +1,582 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/* Tiny language for matching against windows */
++
++/*
++ * Copyright (C) 2009 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ */
++
++#include <glib.h>
++#include <string.h>
++
++#include "window-matcher.h"
++
++typedef struct _MetaWindowMatcher MetaWindowMatcher;
++
++typedef enum {
++ MATCHER_OPERAND_CLASS,
++ MATCHER_OPERAND_NAME
++} MatcherOperand;
++
++typedef enum {
++ MATCHER_TOKEN_AND = G_TOKEN_LAST + 1,
++ MATCHER_TOKEN_OR,
++ MATCHER_TOKEN_NOT,
++ MATCHER_TOKEN_EQ,
++ MATCHER_TOKEN_GLOB,
++ MATCHER_TOKEN_NAME,
++ MATCHER_TOKEN_CLASS
++} MatcherToken;
++
++struct _MetaWindowMatcher {
++ enum {
++ MATCHER_AND,
++ MATCHER_OR,
++ MATCHER_NOT,
++ MATCHER_EQ,
++ MATCHER_GLOB
++ } type;
++
++ union {
++ struct {
++ MetaWindowMatcher *a;
++ MetaWindowMatcher *b;
++ } and;
++ struct {
++ MetaWindowMatcher *a;
++ MetaWindowMatcher *b;
++ } or;
++ struct {
++ MetaWindowMatcher *a;
++ } not;
++ struct {
++ MatcherOperand operand;
++ char *str;
++ } eq;
++ struct {
++ MatcherOperand operand;
++ char *str;
++ GPatternSpec *pattern;
++ } glob;
++ } u;
++};
++
++static void
++meta_window_matcher_free (MetaWindowMatcher *matcher)
++{
++ switch (matcher->type)
++ {
++ case MATCHER_AND:
++ meta_window_matcher_free (matcher->u.and.a);
++ meta_window_matcher_free (matcher->u.and.b);
++ break;
++ case MATCHER_OR:
++ meta_window_matcher_free (matcher->u.or.a);
++ meta_window_matcher_free (matcher->u.or.b);
++ break;
++ case MATCHER_NOT:
++ meta_window_matcher_free (matcher->u.or.a);
++ break;
++ case MATCHER_EQ:
++ g_free (matcher->u.eq.str);
++ break;
++ case MATCHER_GLOB:
++ g_free (matcher->u.glob.str);
++ g_pattern_spec_free (matcher->u.glob.pattern);
++ break;
++ }
++
++ g_slice_free (MetaWindowMatcher, matcher);
++}
++
++void
++meta_window_matcher_list_free (GSList *list)
++{
++ g_slist_foreach (list, (GFunc)meta_window_matcher_free, NULL);
++ g_slist_free (list);
++}
++
++static gboolean
++meta_window_matcher_matches (MetaWindowMatcher *matcher,
++ const char *window_name,
++ const char *window_class)
++{
++ switch (matcher->type)
++ {
++ case MATCHER_AND:
++ return (meta_window_matcher_matches (matcher->u.and.a, window_name, window_class) &&
++ meta_window_matcher_matches (matcher->u.and.b, window_name, window_class));
++ case MATCHER_OR:
++ return (meta_window_matcher_matches (matcher->u.or.a, window_name, window_class) ||
++ meta_window_matcher_matches(matcher->u.or.b, window_name, window_class));
++ case MATCHER_NOT:
++ return !meta_window_matcher_matches (matcher->u.not.a, window_name, window_class);
++ case MATCHER_EQ:
++ if (matcher->u.eq.operand == MATCHER_OPERAND_NAME)
++ return window_name && strcmp (matcher->u.eq.str, window_name) == 0;
++ else
++ return window_class && strcmp (matcher->u.eq.str, window_class) == 0;
++ case MATCHER_GLOB:
++ if (matcher->u.glob.operand == MATCHER_OPERAND_NAME)
++ return window_name && g_pattern_match_string (matcher->u.glob.pattern, window_name);
++ else
++ return window_class && g_pattern_match_string (matcher->u.glob.pattern, window_class);
++ }
++
++ g_assert_not_reached();
++ return FALSE;
++}
++
++gboolean
++meta_window_matcher_list_matches (GSList *list,
++ const char *window_name,
++ const char *window_class)
++{
++ GSList *l;
++
++ for (l = list; l; l = l->next)
++ {
++ if (meta_window_matcher_matches (l->data, window_name, window_class))
++ return TRUE;
++ }
++
++ return FALSE;
++}
++
++static const GScannerConfig scanner_config =
++{
++ " \t\r\n" /* cset_skip_characters */,
++ (
++ G_CSET_a_2_z
++ "_"
++ G_CSET_A_2_Z
++ ) /* cset_identifier_first */,
++ (
++ G_CSET_a_2_z
++ "_"
++ G_CSET_A_2_Z
++ G_CSET_DIGITS
++ G_CSET_LATINS
++ G_CSET_LATINC
++ ) /* cset_identifier_nth */,
++ NULL /* cpair_comment_single */,
++ TRUE /* case_sensitive */,
++ TRUE /* skip_comment_multi */,
++ FALSE /* skip_comment_single */,
++ TRUE /* scan_comment_multi */,
++ TRUE /* scan_identifier */,
++ TRUE /* scan_identifier_1char */,
++ FALSE /* scan_identifier_NULL */,
++ TRUE /* scan_symbols */,
++ FALSE /* scan_binary */,
++ TRUE /* scan_octal */,
++ TRUE /* scan_float */,
++ TRUE /* scan_hex */,
++ FALSE /* scan_hex_dollar */,
++ TRUE /* scan_string_sq */,
++ TRUE /* scan_string_dq */,
++ TRUE /* numbers_2_int */,
++ FALSE /* int_2_float */,
++ FALSE /* identifier_2_string */,
++ TRUE /* char_2_token */,
++ TRUE /* symbol_2_token */,
++ FALSE /* scope_0_fallback */,
++ FALSE /* store_int64 */,
++};
++
++static void
++set_error (GScanner *scanner,
++ GError **error,
++ const char *message)
++{
++ g_set_error (error, 0, 0,
++ "Parse error at %d:%d: %s",
++ g_scanner_cur_line (scanner),
++ g_scanner_cur_position (scanner),
++ message);
++}
++
++static MetaWindowMatcher *
++meta_window_matcher_new_and (MetaWindowMatcher *a,
++ MetaWindowMatcher *b)
++{
++ MetaWindowMatcher *matcher = g_slice_new0 (MetaWindowMatcher);
++
++ matcher->type = MATCHER_AND;
++ matcher->u.and.a = a;
++ matcher->u.and.b = b;
++
++ return matcher;
++}
++
++static MetaWindowMatcher *
++meta_window_matcher_new_or (MetaWindowMatcher *a,
++ MetaWindowMatcher *b)
++{
++ MetaWindowMatcher *matcher = g_slice_new0 (MetaWindowMatcher);
++
++ matcher->type = MATCHER_OR;
++ matcher->u.or.a = a;
++ matcher->u.or.b = b;
++
++ return matcher;
++}
++
++static MetaWindowMatcher *
++meta_window_matcher_new_not (MetaWindowMatcher *a)
++{
++ MetaWindowMatcher *matcher = g_slice_new0 (MetaWindowMatcher);
++
++ matcher->type = MATCHER_NOT;
++ matcher->u.not.a = a;
++
++ return matcher;
++}
++
++static MetaWindowMatcher *
++meta_window_matcher_new_eq (MatcherOperand operand,
++ const char *str)
++{
++ MetaWindowMatcher *matcher = g_slice_new0 (MetaWindowMatcher);
++
++ matcher->type = MATCHER_EQ;
++ matcher->u.eq.operand = operand;
++ matcher->u.eq.str = g_strdup (str);
++
++ return matcher;
++}
++
++static MetaWindowMatcher *
++meta_window_matcher_new_glob (MatcherOperand operand,
++ const char *str)
++{
++ MetaWindowMatcher *matcher = g_slice_new0 (MetaWindowMatcher);
++
++ matcher->type = MATCHER_GLOB;
++ matcher->u.glob.operand = operand;
++ matcher->u.glob.str = g_strdup (str);
++ matcher->u.glob.pattern = g_pattern_spec_new (str);
++
++ return matcher;
++}
++
++static MetaWindowMatcher *
++meta_window_matcher_from_scanner (GScanner *scanner,
++ GError **error)
++{
++ MetaWindowMatcher *matcher = NULL;
++ GTokenType token;
++ GTokenValue value;
++
++ token = g_scanner_get_next_token (scanner);
++ if (token != G_TOKEN_LEFT_PAREN)
++ {
++ set_error (scanner, error, "expected '('");
++ return NULL;
++ }
++
++ token = g_scanner_get_next_token (scanner);
++ switch (token)
++ {
++ case MATCHER_TOKEN_AND:
++ case MATCHER_TOKEN_OR:
++ case MATCHER_TOKEN_NOT:
++ {
++ MetaWindowMatcher *a, *b;
++
++ a = meta_window_matcher_from_scanner (scanner, error);
++ if (!a)
++ return NULL;
++
++ if (token != MATCHER_TOKEN_NOT)
++ {
++ b = meta_window_matcher_from_scanner (scanner, error);
++ if (!b)
++ {
++ meta_window_matcher_free (a);
++ return NULL;
++ }
++ }
++
++ switch (token)
++ {
++ case MATCHER_TOKEN_AND:
++ matcher = meta_window_matcher_new_and (a, b);
++ break;
++ case MATCHER_TOKEN_OR:
++ matcher = meta_window_matcher_new_or (a, b);
++ break;
++ case MATCHER_TOKEN_NOT:
++ matcher = meta_window_matcher_new_not (a);
++ break;
++ default:
++ g_assert_not_reached();
++ break;
++ }
++ }
++ break;
++ case MATCHER_TOKEN_EQ:
++ case MATCHER_TOKEN_GLOB:
++ {
++ MatcherOperand operand;
++
++ switch (g_scanner_get_next_token (scanner))
++ {
++ case MATCHER_TOKEN_NAME:
++ operand = MATCHER_OPERAND_NAME;
++ break;
++ case MATCHER_TOKEN_CLASS:
++ operand = MATCHER_OPERAND_CLASS;
++ break;
++ default:
++ set_error (scanner, error, "expected name/class");
++ return NULL;
++ }
++
++ if (g_scanner_get_next_token (scanner) != G_TOKEN_STRING)
++ {
++ set_error (scanner, error, "expected string");
++ return NULL;
++ }
++
++ value = g_scanner_cur_value (scanner);
++
++ switch (token)
++ {
++ case MATCHER_TOKEN_EQ:
++ matcher = meta_window_matcher_new_eq (operand, value.v_string);
++ break;
++ case MATCHER_TOKEN_GLOB:
++ matcher = meta_window_matcher_new_glob (operand, value.v_string);
++ break;
++ default:
++ g_assert_not_reached();
++ }
++ }
++ break;
++ default:
++ set_error (scanner, error, "expected and/or/not/eq/glob");
++ return NULL;
++ }
++
++ if (g_scanner_get_next_token (scanner) != G_TOKEN_RIGHT_PAREN)
++ {
++ set_error (scanner, error, "expected ')'");
++ return NULL;
++ }
++
++ return matcher;
++}
++
++GSList *
++meta_window_matcher_list_from_string (const char *str,
++ GError **error)
++{
++ GScanner *scanner = g_scanner_new (&scanner_config);
++ GSList *result = NULL;
++
++ g_scanner_scope_add_symbol (scanner, 0, "and", GINT_TO_POINTER (MATCHER_TOKEN_AND));
++ g_scanner_scope_add_symbol (scanner, 0, "or", GINT_TO_POINTER (MATCHER_TOKEN_OR));
++ g_scanner_scope_add_symbol (scanner, 0, "not", GINT_TO_POINTER (MATCHER_TOKEN_NOT));
++ g_scanner_scope_add_symbol (scanner, 0, "eq", GINT_TO_POINTER (MATCHER_TOKEN_EQ));
++ g_scanner_scope_add_symbol (scanner, 0, "glob", GINT_TO_POINTER (MATCHER_TOKEN_GLOB));
++ g_scanner_scope_add_symbol (scanner, 0, "name", GINT_TO_POINTER (MATCHER_TOKEN_NAME));
++ g_scanner_scope_add_symbol (scanner, 0, "class", GINT_TO_POINTER (MATCHER_TOKEN_CLASS));
++
++ g_scanner_input_text (scanner, str, strlen (str));
++
++ while (g_scanner_peek_next_token (scanner) != G_TOKEN_EOF)
++ {
++ MetaWindowMatcher *matcher = meta_window_matcher_from_scanner (scanner, error);
++ if (!matcher)
++ {
++ meta_window_matcher_list_free (result);
++ return NULL;
++ }
++
++ result = g_slist_prepend (result, matcher);
++ }
++
++ g_scanner_destroy (scanner);
++
++ return g_slist_reverse (result);
++}
++
++#ifdef BUILD_MATCHER_TESTS
++
++static void
++append_operand_to_string (GString *string,
++ MatcherOperand operand)
++{
++ if (operand == MATCHER_OPERAND_NAME)
++ g_string_append (string, "name");
++ else
++ g_string_append (string, "class");
++}
++
++static void
++append_string_to_string (GString *str,
++ const char *to_append)
++{
++ const char *p;
++
++ g_string_append_c (str, '"');
++ for (p = to_append; *p; p++)
++ {
++ if (*p == '"')
++ g_string_append (str, "\\\"");
++ else
++ g_string_append_c (str, *p);
++ }
++ g_string_append_c (str, '"');
++}
++
++static void
++append_matcher_to_string (GString *str,
++ MetaWindowMatcher *matcher)
++{
++ switch (matcher->type)
++ {
++ case MATCHER_AND:
++ g_string_append (str, "(and ");
++ append_matcher_to_string (str, matcher->u.and.a);
++ g_string_append_c (str, ' ');
++ append_matcher_to_string (str, matcher->u.and.b);
++ break;
++ case MATCHER_OR:
++ g_string_append (str, "(or ");
++ append_matcher_to_string (str, matcher->u.or.a);
++ g_string_append_c (str, ' ');
++ append_matcher_to_string (str, matcher->u.or.b);
++ break;
++ case MATCHER_NOT:
++ g_string_append (str, "(not ");
++ append_matcher_to_string (str, matcher->u.not.a);
++ break;
++ case MATCHER_EQ:
++ g_string_append (str, "(eq ");
++ append_operand_to_string (str, matcher->u.eq.operand);
++ g_string_append_c (str, ' ');
++ append_string_to_string (str, matcher->u.eq.str);
++ break;
++ case MATCHER_GLOB:
++ g_string_append (str, "(glob ");
++ append_operand_to_string (str, matcher->u.glob.operand);
++ g_string_append_c (str, ' ');
++ append_string_to_string (str, matcher->u.glob.str);
++ break;
++ }
++
++ g_string_append_c (str, ')');
++}
++
++static char *
++meta_window_matcher_list_to_string (GSList *list)
++{
++ GSList *l;
++ GString *str = g_string_new (NULL);
++
++ for (l = list; l; l = l->next)
++ {
++ if (str->len > 0)
++ g_string_append_c (str, ' ');
++
++ append_matcher_to_string (str, l->data);
++ }
++
++ return g_string_free (str, FALSE);
++}
++
++static void
++test_roundtrip (const char *str)
++{
++ GError *error = NULL;
++ GSList *list = meta_window_matcher_list_from_string (str, &error);
++ char *result;
++
++ if (error != NULL)
++ g_error ("Failed to parse '%s': %s\n", str, error->message);
++
++ result = meta_window_matcher_list_to_string (list);
++ if (strcmp (result, str) != 0)
++ g_error ("Round-trip conversion of '%s' gave '%s'\n", str, result);
++
++ g_free (result);
++ meta_window_matcher_list_free (list);
++}
++
++static void
++test_matches (const char *str,
++ const char *window_name,
++ const char *window_class,
++ gboolean expected)
++{
++ GError *error = NULL;
++ GSList *list = meta_window_matcher_list_from_string (str, &error);
++ gboolean matches;
++
++ if (error != NULL)
++ g_error ("Failed to parse '%s': %s\n", str, error->message);
++
++ matches = meta_window_matcher_list_matches (list, window_name, window_class))
++ if (matches != expected)
++ {
++ g_error ("Tested '%s' against name=%s, class=%s, expected %s, got %s\n",
++ str, window_name, window_class,
++ expected ? "true" : "false",
++ matches ? "true" : "false");
++ }
++
++
++ meta_window_matcher_list_free (list);
++}
++
++int main (int argc, char **argv)
++{
++ test_roundtrip ("(eq name \"foo\")");
++ test_roundtrip ("(eq name \"fo\\\"o\")");
++ test_roundtrip ("(glob class \"*bar?baz\")");
++ test_roundtrip ("(and (eq name \"foo\") (glob class \"*bar?baz\"))");
++ test_roundtrip ("(or (eq name \"foo\") (glob class \"*bar?baz\"))");
++ test_roundtrip ("(not (eq name \"foo\"))");
++
++ test_roundtrip ("(eq name \"foo\") (glob class \"*bar?baz\")");
++
++ test_matches ("(eq name 'foo')", "foo", NULL, TRUE);
++ test_matches ("(eq name 'foo')", "foob", NULL, FALSE);
++ test_matches ("(eq name 'foo')", NULL, NULL, FALSE);
++ test_matches ("(eq class 'bar')", "foo", "bar", TRUE);
++ test_matches ("(eq class 'bar')", NULL, NULL, FALSE);
++
++ test_matches ("(glob name 'foo*')", "foooo", NULL, TRUE);
++ test_matches ("(glob name 'foo*')", NULL, NULL, FALSE);
++ test_matches ("(glob class 'b*r')", "foooo", "baaaar", TRUE);
++ test_matches ("(glob class 'b*r')", NULL, NULL, FALSE);
++
++ test_matches ("(and (eq name 'foo') (eq class 'bar'))", "foo", "bar", TRUE);
++ test_matches ("(and (eq name 'foo') (eq class 'bar'))", "foo", "baz", FALSE);
++ test_matches ("(and (eq name 'foo') (not (eq class 'bar')))", "foo", "bar", FALSE);
++ test_matches ("(and (eq name 'foo') (not (eq class 'bar')))", "foo", "baz", TRUE);
++
++ test_matches ("(or (eq name 'foo') (eq class 'bar'))", "foo", "baz", TRUE);
++ test_matches ("(or (eq name 'foo') (eq class 'bar'))", "fof", "baz", FALSE);
++
++ return 0;
++}
++
++#endif /* BUILD_MATCHER_TESTS */
+diff --git a/src/core/window-matcher.h b/src/core/window-matcher.h
+new file mode 100644
+index 0000000..7fc7826
+--- /dev/null
++++ b/src/core/window-matcher.h
+@@ -0,0 +1,46 @@
++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
++
++/* Tiny language for matching against windows
++ *
++ * Expression Syntax:
++ *
++ * (and <expr> <expr>)
++ * (or <expr> <expr>)
++ * (not <expr>)
++ * (eq [name|class] "<value>")
++ * (glob [name|class] "<glob>")
++ *
++ * A "matcher list" is a whitespace-separated list of expressions that are
++ * implicitly or'ed together. Globs are shell style patterns with
++ * matching 0 or more characters and ? matching one character.
++ */
++
++/*
++ * Copyright (C) 2009 Red Hat, Inc.
++ *
++ * 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_WINDOW_MATCHER_H
++#define META_WINDOW_MATCHER_H
++
++GSList * meta_window_matcher_list_from_string (const char *str,
++ GError **error);
++void meta_window_matcher_list_free (GSList *list);
++gboolean meta_window_matcher_list_matches (GSList *list,
++ const char *window_name,
++ const char *window_class);
++#endif /* META_WINDOW_MATCHER_H */
+diff --git a/src/core/window.c b/src/core/window.c
+index 8d029a2..10da47a 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -1965,7 +1965,14 @@ window_state_on_map (MetaWindow *window,
+ {
+ gboolean intervening_events;
+
+- intervening_events = intervening_user_event_occurred (window);
++ /* A 'no focus' window is a window that has been configured in GConf
++ * to never take focus on map; typically it will be a notification
++ * window from a legacy app that doesn't support _NET_WM_USER_TIME.
++ */
++ if (meta_prefs_window_is_no_focus (window->title, window->res_class))
++ intervening_events = TRUE;
++ else
++ intervening_events = intervening_user_event_occurred (window);
+
+ *takes_focus = !intervening_events;
+ *places_on_top = *takes_focus;
+diff --git a/src/include/prefs.h b/src/include/prefs.h
+index a4193ff..6698dfe 100644
+--- a/src/include/prefs.h
++++ b/src/include/prefs.h
+@@ -60,7 +60,8 @@ typedef enum
+ META_PREF_CURSOR_SIZE,
+ META_PREF_COMPOSITING_MANAGER,
+ META_PREF_RESIZE_WITH_RIGHT_BUTTON,
+- META_PREF_FORCE_FULLSCREEN
++ META_PREF_FORCE_FULLSCREEN,
++ META_PREF_NO_FOCUS_WINDOWS
+ } MetaPreference;
+
+ typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
+@@ -106,6 +107,9 @@ MetaActionTitlebar meta_prefs_get_action_double_click_titlebar (void);
+ MetaActionTitlebar meta_prefs_get_action_middle_click_titlebar (void);
+ MetaActionTitlebar meta_prefs_get_action_right_click_titlebar (void);
+
++gboolean meta_prefs_window_is_no_focus (const char *window_name,
++ const char *window_class);
++
+ void meta_prefs_set_num_workspaces (int n_workspaces);
+
+ const char* meta_prefs_get_workspace_name (int i);
+diff --git a/src/metacity.schemas.in.in b/src/metacity.schemas.in.in
+index a9dd397..34cd7d6 100644
+--- a/src/metacity.schemas.in.in
++++ b/src/metacity.schemas.in.in
+@@ -100,6 +100,34 @@
+ </schema>
+
+ <schema>
++ <key>/schemas/apps/metacity/general/no_focus_windows</key>
++ <applyto>/apps/metacity/general/no_focus_windows</applyto>
++ <owner>metacity</owner>
++ <type>string</type>
++ <default></default>
++ <locale name="C">
++ <short>New windows that shouldn't get focus</short>
++ <long>
++ This option provides a way to specify new windows that shouldn't get
++ focus. Normally an application specifies whether or not it gets focus
++ by setting the _NET_WM_USER_TIME property, but legacy applications
++ may not set this, which can cause unwanted focus stealing.
++
++ The contents of this property is a space-separated list of expressions
++ to match against windows. If any of the expressions match a window
++ then the window will not get focus. The syntax of expressions is:
++
++ (eq [name|class] "&lt;value&gt;"): window name (title) or the class from
++ WM_CLASS matches &lt;value&gt; exactly.
++ (glob [name|class] "&lt;glob&gt;"): window name (title) or the class from
++ WM_CLASS matches the shell-style glob pattern &lt;glob&gt;.
++ (and &lt;expr&gt; &lt;expr&gt;) (or &lt;expr&gt; &lt;expr&gt;) (not &lt;expr): Boolean combinations
++ of expressions.
++ </long>
++ </locale>
++ </schema>
++
++ <schema>
+ <key>/schemas/apps/metacity/general/raise_on_click</key>
+ <applyto>/apps/metacity/general/raise_on_click</applyto>
+ <owner>metacity</owner>
diff --git a/Allow-applications-to-raise-windows-when-raise_on_cl.patch b/Allow-applications-to-raise-windows-when-raise_on_cl.patch
new file mode 100644
index 0000000..20d8dfa
--- /dev/null
+++ b/Allow-applications-to-raise-windows-when-raise_on_cl.patch
@@ -0,0 +1,31 @@
+From 55d4c4cc9455f348b5bc455675004a0e035ea31d Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Tue, 17 Nov 2009 17:24:53 -0500
+Subject: [PATCH] Allow applications to raise windows when raise_on_click is off
+
+Whether Metacity honors a raise request from an application should
+not be affected by the raise_on_click setting; remove a check that
+seems to have been added in error.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=445447
+---
+ src/core/window.c | 3 +--
+ 1 files changed, 1 insertions(+), 2 deletions(-)
+
+diff --git a/src/core/window.c b/src/core/window.c
+index b481ccf..db59de1 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -4716,8 +4716,7 @@ meta_window_configure_request (MetaWindow *window,
+ {
+ MetaWindow *active_window;
+ active_window = window->display->expected_focus_window;
+- if (meta_prefs_get_disable_workarounds () ||
+- !meta_prefs_get_raise_on_click ())
++ if (meta_prefs_get_disable_workarounds ())
+ {
+ meta_topic (META_DEBUG_STACK,
+ "%s sent an xconfigure stacking request; this is "
+--
+1.6.5.2
+
diff --git a/Allow-explicit-raises-from-same-client-not-just-sa.patch b/Allow-explicit-raises-from-same-client-not-just-sa.patch
new file mode 100644
index 0000000..2db720a
--- /dev/null
+++ b/Allow-explicit-raises-from-same-client-not-just-sa.patch
@@ -0,0 +1,73 @@
+From 7e116a394689718567406837740679c1f1f0d74f Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Mon, 19 Oct 2009 19:41:54 -0400
+Subject: [PATCH] Allow explicit raises from same client, not just same app
+
+We currently allow XRaiseWindow when the same application (defined
+by the window group) is focused, but the kind of old applications
+that XRaiseWindow are frequently not setting the window group.
+
+Expand the check to allow the same X client (defined by the looking
+at client ID) to raise windows above the focus window.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=567528
+---
+ src/core/window.c | 22 ++++++++++++++++++++++
+ 1 files changed, 22 insertions(+), 0 deletions(-)
+
+diff --git a/src/core/window.c b/src/core/window.c
+index 6de86ee..8d029a2 100644
+--- a/src/core/window.c
++++ b/src/core/window.c
+@@ -47,6 +47,7 @@
+ #include "effects.h"
+
+ #include <X11/Xatom.h>
++#include <X11/Xlibint.h> /* For display->resource_mask */
+ #include <string.h>
+
+ #ifdef HAVE_SHAPE
+@@ -72,6 +73,9 @@ static gboolean process_property_notify (MetaWindow *window,
+ static void meta_window_show (MetaWindow *window);
+ static void meta_window_hide (MetaWindow *window);
+
++static gboolean meta_window_same_client (MetaWindow *window,
++ MetaWindow *other_window);
++
+ static void meta_window_save_rect (MetaWindow *window);
+ static void save_user_window_placement (MetaWindow *window);
+ static void force_save_user_window_placement (MetaWindow *window);
+@@ -4708,6 +4712,7 @@ meta_window_configure_request (MetaWindow *window,
+ }
+ else if (active_window &&
+ !meta_window_same_application (window, active_window) &&
++ !meta_window_same_client (window, active_window) &&
+ XSERVER_TIME_IS_BEFORE (window->net_wm_user_time,
+ active_window->net_wm_user_time))
+ {
+@@ -7544,6 +7549,23 @@ meta_window_same_application (MetaWindow *window,
+ group==other_group;
+ }
+
++/* Generally meta_window_same_application() is a better idea
++ * of "sameness", since it handles the case where multiple apps
++ * want to look like the same app or the same app wants to look
++ * like multiple apps, but in the case of workarounds for legacy
++ * applications (which likely aren't setting the group properly
++ * anyways), it may be desirable to check this as well.
++ */
++static gboolean
++meta_window_same_client (MetaWindow *window,
++ MetaWindow *other_window)
++{
++ int resource_mask = window->display->xdisplay->resource_mask;
++
++ return ((window->xwindow & ~resource_mask) ==
++ (other_window->xwindow & ~resource_mask));
++}
++
+ void
+ meta_window_refresh_resize_popup (MetaWindow *window)
+ {
+--
+1.6.5.rc2 \ No newline at end of file
diff --git a/Dont-focus-ancestor-window-on-a-different-workspac.patch b/Dont-focus-ancestor-window-on-a-different-workspac.patch
new file mode 100644
index 0000000..be67d0d
--- /dev/null
+++ b/Dont-focus-ancestor-window-on-a-different-workspac.patch
@@ -0,0 +1,39 @@
+From a17fb47e08257d09e1e795e8114b21b134b1f3c2 Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Mon, 19 Oct 2009 18:43:00 -0400
+Subject: [PATCH] Don't focus ancestor window on a different workspace
+
+When we are moving a window with a modal dialog to a different
+workspace, meta_workspace_focus_default_window() can be called
+with 'not_this_one' being the focused modal dialog.
+
+Since the ancestor of that window is also being moved, we must
+not focus it as an alternative to the current window; this will
+cause windows to be moved back and Metacity to get into an
+inconsistent confused state.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=237158
+
+https://bugzilla.gnome.org/show_bug.cgi?id=598995
+---
+ src/core/workspace.c | 5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/src/core/workspace.c b/src/core/workspace.c
+index a0170a6..92993a7 100644
+--- a/src/core/workspace.c
++++ b/src/core/workspace.c
+@@ -969,7 +969,10 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
+ MetaWindow *ancestor;
+ ancestor = NULL;
+ meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
+- if (ancestor != NULL)
++ if (ancestor != NULL &&
++ (ancestor->on_all_workspaces ||
++ ancestor->workspace == workspace) &&
++ meta_window_showing_on_its_workspace (ancestor))
+ {
+ meta_topic (META_DEBUG_FOCUS,
+ "Focusing %s, ancestor of %s\n",
+--
+1.6.5.rc2 \ No newline at end of file
diff --git a/Dont-warn-about-a-missing-session-file.patch b/Dont-warn-about-a-missing-session-file.patch
new file mode 100644
index 0000000..6173646
--- /dev/null
+++ b/Dont-warn-about-a-missing-session-file.patch
@@ -0,0 +1,36 @@
+From 3b06d1045cc990a8610bdbd5c9b83440b1b6e932 Mon Sep 17 00:00:00 2001
+From: Tomislav Vujec <tvujec@gmail.com>
+Date: Tue, 17 Nov 2009 19:42:38 -0500
+Subject: [PATCH] Don't warn about a missing session file
+
+When started without session related command line parameters (e.g. from
+gnome-session), metacity picks up client_id from the DESKTOP_AUTOSTART_ID
+environment variable. Unfortunately, there is no way to distinguish if this was
+passed from a config file, representing old saved session, or generated by
+gnome-session, therefore load_state is attempted in each case. If the client_id
+is generated, there will be no session file, and metacity will report a
+warning.
+
+Just remove the warning so that users won't always find a warning at the
+start of their .xsession-errors.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=577576
+---
+ src/core/session.c | 2 --
+ 1 files changed, 0 insertions(+), 2 deletions(-)
+
+diff --git a/src/core/session.c b/src/core/session.c
+index 7e3b389..32fda97 100644
+--- a/src/core/session.c
++++ b/src/core/session.c
+@@ -1098,8 +1098,6 @@ load_state (const char *previous_save_file)
+ {
+ /* oh, just give up */
+
+- meta_warning (_("Failed to read saved session file %s: %s\n"),
+- canonical_session_file, error->message);
+ g_error_free (error);
+ g_free (session_file);
+ g_free (canonical_session_file);
+--
+1.6.5.2 \ No newline at end of file
diff --git a/For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch b/For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch
new file mode 100644
index 0000000..be5a7ce
--- /dev/null
+++ b/For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch
@@ -0,0 +1,394 @@
+From e8a6af29a1f57024067a12567e2bd906e6bad5a4 Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Tue, 20 Oct 2009 15:13:45 -0400
+Subject: [PATCH] For mouse and sloppy focus, return to "mouse mode" on motion
+
+For mouse and sloppy focus, there are various cases where the focus
+window can be moved away from the focus window. Mostly these relate
+to "display->mouse_mode = FALSE", which we enter when the user
+starts keynav'ing, but it can also occur if a window is focus-denied
+mapped and mapped under the pointer.
+
+Prior to this patch, there was no fast way for the user to start
+interacting with the window - if they just clicked on the window,
+the click would be passed through, and could disturb the windows
+contents, so the user had to either mouse out and then mouse back
+in, or go up and click on the titlebar.
+
+With this patch, when we get into this state, we add a timeout
+and poll for pointer motion with XQueryPointer. If the user then
+moves the pointer (more than a single pixel to handle jitter),
+we focus the window under the pointer and return to mouse mode.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=599097
+---
+ src/core/display-private.h | 11 ++
+ src/core/display.c | 239 +++++++++++++++++++++++++++++++++++--------
+ src/core/keybindings.c | 10 +-
+ 3 files changed, 210 insertions(+), 50 deletions(-)
+
+diff --git a/src/core/display-private.h b/src/core/display-private.h
+index 19287f3..b14d7d7 100644
+--- a/src/core/display-private.h
++++ b/src/core/display-private.h
+@@ -150,6 +150,14 @@ struct _MetaDisplay
+ guint autoraise_timeout_id;
+ MetaWindow* autoraise_window;
+
++ /* When we ignore an enter due to !display->mouse_mode, a timeout
++ * to check if the mouse is moved, in which case we should focus
++ * the pointer window and return to mouse mode */
++ guint focus_on_motion_timeout_id;
++ Window focus_on_motion_start_root_window;
++ int focus_on_motion_start_x;
++ int focus_on_motion_start_y;
++
+ /* Alt+click button grabs */
+ unsigned int window_grab_modifiers;
+
+@@ -497,4 +505,7 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
+ MetaWindow *window);
+ void meta_display_remove_autoraise_callback (MetaDisplay *display);
+
++void meta_display_disable_mouse_mode (MetaDisplay *display);
++void meta_display_enable_mouse_mode (MetaDisplay *display);
++
+ #endif
+diff --git a/src/core/display.c b/src/core/display.c
+index 55c374a..78139bd 100644
+--- a/src/core/display.c
++++ b/src/core/display.c
+@@ -165,6 +165,9 @@ static void sanity_check_timestamps (MetaDisplay *display,
+
+ MetaGroup* get_focussed_group (MetaDisplay *display);
+
++static void start_focus_on_motion (MetaDisplay *display);
++static void stop_focus_on_motion (MetaDisplay *display);
++
+ /**
+ * Destructor for MetaPingData structs. Will destroy the
+ * event source for the struct as well.
+@@ -876,6 +879,7 @@ meta_display_close (MetaDisplay *display,
+ meta_prefs_remove_listener (prefs_changed_callback, display);
+
+ meta_display_remove_autoraise_callback (display);
++ stop_focus_on_motion (display);
+
+ if (display->grab_old_window_stacking)
+ g_list_free (display->grab_old_window_stacking);
+@@ -1816,67 +1820,86 @@ event_callback (XEvent *event,
+ if (window && !serial_is_ignored (display, event->xany.serial) &&
+ event->xcrossing.mode != NotifyGrab &&
+ event->xcrossing.mode != NotifyUngrab &&
+- event->xcrossing.detail != NotifyInferior &&
+- meta_display_focus_sentinel_clear (display))
++ event->xcrossing.detail != NotifyInferior)
+ {
+ switch (meta_prefs_get_focus_mode ())
+ {
+ case META_FOCUS_MODE_SLOPPY:
+ case META_FOCUS_MODE_MOUSE:
+- display->mouse_mode = TRUE;
+- if (window->type != META_WINDOW_DOCK &&
+- window->type != META_WINDOW_DESKTOP)
++ if (!meta_display_focus_sentinel_clear (display))
+ {
+- meta_topic (META_DEBUG_FOCUS,
+- "Focusing %s due to enter notify with serial %lu "
+- "at time %lu, and setting display->mouse_mode to "
+- "TRUE.\n",
+- window->desc,
+- event->xany.serial,
+- event->xcrossing.time);
+-
+- meta_window_focus (window, event->xcrossing.time);
+-
+- /* stop ignoring stuff */
+- reset_ignores (display);
+-
+- if (meta_prefs_get_auto_raise ())
++ /* There was an enter event that we want to ignore because
++ * we're in "keynav mode" or because we are mapping
++ * a focus-denied window; the next time the mouse is moved
++ * we want to focus the window so the user doesn't have
++ * to click (possibly messing up window contents) or
++ * enter/leave to get focus to the window.
++ *
++ * (This check will also trigger for visual bell flashes
++ * but it doesn't really do any harm to check for motion
++ * in that case, since the next motion will just result in
++ * the current window being focused.)
++ */
++ start_focus_on_motion (display);
++ }
++ else
++ {
++ meta_display_enable_mouse_mode (display);
++ if (window->type != META_WINDOW_DOCK &&
++ window->type != META_WINDOW_DESKTOP)
+ {
+- meta_display_queue_autoraise_callback (display, window);
++ meta_topic (META_DEBUG_FOCUS,
++ "Focusing %s due to enter notify with serial %lu "
++ "at time %lu, and setting display->mouse_mode to "
++ "TRUE.\n",
++ window->desc,
++ event->xany.serial,
++ event->xcrossing.time);
++
++ meta_window_focus (window, event->xcrossing.time);
++
++ /* stop ignoring stuff */
++ reset_ignores (display);
++
++ if (meta_prefs_get_auto_raise ())
++ {
++ meta_display_queue_autoraise_callback (display, window);
++ }
++ else
++ {
++ meta_topic (META_DEBUG_FOCUS,
++ "Auto raise is disabled\n");
++ }
+ }
+- else
++ /* In mouse focus mode, we defocus when the mouse *enters*
++ * the DESKTOP window, instead of defocusing on LeaveNotify.
++ * This is because having the mouse enter override-redirect
++ * child windows unfortunately causes LeaveNotify events that
++ * we can't distinguish from the mouse actually leaving the
++ * toplevel window as we expect. But, since we filter out
++ * EnterNotify events on override-redirect windows, this
++ * alternative mechanism works great.
++ */
++ if (window->type == META_WINDOW_DESKTOP &&
++ meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
++ display->expected_focus_window != NULL)
+ {
+ meta_topic (META_DEBUG_FOCUS,
+- "Auto raise is disabled\n");
++ "Unsetting focus from %s due to mouse entering "
++ "the DESKTOP window\n",
++ display->expected_focus_window->desc);
++ meta_display_focus_the_no_focus_window (display,
++ window->screen,
++ event->xcrossing.time);
+ }
+ }
+- /* In mouse focus mode, we defocus when the mouse *enters*
+- * the DESKTOP window, instead of defocusing on LeaveNotify.
+- * This is because having the mouse enter override-redirect
+- * child windows unfortunately causes LeaveNotify events that
+- * we can't distinguish from the mouse actually leaving the
+- * toplevel window as we expect. But, since we filter out
+- * EnterNotify events on override-redirect windows, this
+- * alternative mechanism works great.
+- */
+- if (window->type == META_WINDOW_DESKTOP &&
+- meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
+- display->expected_focus_window != NULL)
+- {
+- meta_topic (META_DEBUG_FOCUS,
+- "Unsetting focus from %s due to mouse entering "
+- "the DESKTOP window\n",
+- display->expected_focus_window->desc);
+- meta_display_focus_the_no_focus_window (display,
+- window->screen,
+- event->xcrossing.time);
+- }
+ break;
+ case META_FOCUS_MODE_CLICK:
+ break;
+ }
+-
+- if (window->type == META_WINDOW_DOCK)
++
++ if (window->type == META_WINDOW_DOCK &&
++ meta_display_focus_sentinel_clear (display))
+ meta_window_raise (window);
+ }
+ break;
+@@ -5140,6 +5163,132 @@ meta_display_remove_autoraise_callback (MetaDisplay *display)
+ }
+ }
+
++#define FOCUS_ON_MOTION_CHECK_INTERVAL 200 /* 0.2 seconds */
++#define FOCUS_ON_MOTION_THRESHOLD 2 /* Must move 2 pixels */
++
++static gboolean
++check_focus_on_motion (gpointer data)
++{
++ MetaDisplay *display = data;
++ Window root, child;
++ int root_x, root_y;
++ int window_x, window_y;
++ guint mask;
++
++ XQueryPointer (display->xdisplay,
++ DefaultRootWindow (display->xdisplay),
++ &root, &child,
++ &root_x, &root_y,
++ &window_x, &window_y,
++ &mask);
++
++ if (root != display->focus_on_motion_start_root_window ||
++ MAX (ABS (root_x - display->focus_on_motion_start_x),
++ ABS (root_y - display->focus_on_motion_start_y)) >= FOCUS_ON_MOTION_THRESHOLD)
++ {
++ MetaScreen *screen;
++
++ meta_topic (META_DEBUG_FOCUS,
++ "Returning to mouse mode on mouse motion\n");
++
++ meta_display_enable_mouse_mode (display);
++
++ screen = meta_display_screen_for_root (display, root);
++ if (screen != NULL)
++ {
++ MetaWindow *window = meta_screen_get_mouse_window (screen, NULL);
++ guint32 timestamp = meta_display_get_current_time_roundtrip (display);
++
++ if (window &&
++ window->type != META_WINDOW_DOCK &&
++ window->type != META_WINDOW_DESKTOP)
++ {
++ meta_topic (META_DEBUG_FOCUS,
++ "Focusing mouse window %s\n", window->desc);
++
++ meta_window_focus (window, timestamp);
++
++ if (display->autoraise_window != window &&
++ meta_prefs_get_auto_raise ())
++ {
++ meta_display_queue_autoraise_callback (display, window);
++ }
++ }
++ else if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_MOUSE)
++ {
++ meta_topic (META_DEBUG_FOCUS,
++ "Setting focus to no_focus_windowm, since no mouse window.\n");
++ meta_display_focus_the_no_focus_window (display, screen, timestamp);
++ }
++
++ /* for META_FOCUS_MODE_SLOPPY, if the pointer isn't over a window, we just
++ * leave the last window focused */
++ }
++ }
++
++ return TRUE;
++}
++
++static void
++start_focus_on_motion (MetaDisplay *display)
++{
++ if (!display->focus_on_motion_timeout_id)
++ {
++ Window child;
++ guint mask;
++ int window_x, window_y;
++
++ XQueryPointer (display->xdisplay,
++ DefaultRootWindow (display->xdisplay),
++ &display->focus_on_motion_start_root_window,
++ &child,
++ &display->focus_on_motion_start_x,
++ &display->focus_on_motion_start_y,
++ &window_x, &window_y,
++ &mask);
++
++ display->focus_on_motion_timeout_id =
++ g_timeout_add (FOCUS_ON_MOTION_CHECK_INTERVAL,
++ check_focus_on_motion,
++ display);
++ }
++}
++
++static void
++stop_focus_on_motion (MetaDisplay *display)
++{
++ if (display->focus_on_motion_timeout_id)
++ {
++ g_source_remove (display->focus_on_motion_timeout_id);
++ display->focus_on_motion_timeout_id = 0;
++ }
++}
++
++void
++meta_display_disable_mouse_mode (MetaDisplay *display)
++{
++ display->mouse_mode = FALSE;
++
++ /* mouse_mode disabled means that we are now allowing the
++ * mouse window to be different from the focus window;
++ * that discrepancy might not come until we ignore some
++ * enter event, but in a case like tabbing away from the
++ * mouse window, it occurs immediately, so we need to
++ * start checking for motion events to see if we should
++ * focus the mouse window and return to mouse mode.
++ */
++ if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK)
++ start_focus_on_motion (display);
++}
++
++void
++meta_display_enable_mouse_mode (MetaDisplay *display)
++{
++ display->mouse_mode = TRUE;
++
++ stop_focus_on_motion (display);
++}
++
+ #ifdef HAVE_COMPOSITE_EXTENSIONS
+ void
+ meta_display_get_compositor_version (MetaDisplay *display,
+diff --git a/src/core/keybindings.c b/src/core/keybindings.c
+index 63596bb..7d9130f 100644
+--- a/src/core/keybindings.c
++++ b/src/core/keybindings.c
+@@ -2027,7 +2027,7 @@ process_tab_grab (MetaDisplay *display,
+ meta_topic (META_DEBUG_FOCUS, "Activating %s due to tab popup "
+ "selection and turning mouse_mode off\n",
+ target_window->desc);
+- display->mouse_mode = FALSE;
++ meta_display_disable_mouse_mode (display);
+ meta_window_activate (target_window, event->xkey.time);
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+@@ -2763,7 +2763,7 @@ handle_panel (MetaDisplay *display,
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Sending panel message with timestamp %lu, and turning mouse_mode "
+ "off due to keybinding press\n", event->xkey.time);
+- display->mouse_mode = FALSE;
++ meta_display_disable_mouse_mode (display);
+
+ meta_error_trap_push (display);
+
+@@ -2886,7 +2886,7 @@ do_choose_window (MetaDisplay *display,
+ "Activating %s and turning off mouse_mode due to "
+ "switch/cycle windows with no modifiers\n",
+ initial_selection->desc);
+- display->mouse_mode = FALSE;
++ meta_display_disable_mouse_mode (display);
+ meta_window_activate (initial_selection, event->xkey.time);
+ }
+ else if (meta_display_begin_grab_op (display,
+@@ -2915,7 +2915,7 @@ do_choose_window (MetaDisplay *display,
+ "modifier was released prior to grab\n",
+ initial_selection->desc);
+ meta_display_end_grab_op (display, event->xkey.time);
+- display->mouse_mode = FALSE;
++ meta_display_disable_mouse_mode (display);
+ meta_window_activate (initial_selection, event->xkey.time);
+ }
+ else
+@@ -3156,7 +3156,7 @@ handle_move_to_workspace (MetaDisplay *display,
+ meta_topic (META_DEBUG_FOCUS,
+ "Resetting mouse_mode to FALSE due to "
+ "handle_move_to_workspace() call with flip set.\n");
+- workspace->screen->display->mouse_mode = FALSE;
++ meta_display_disable_mouse_mode (display);
+ meta_workspace_activate_with_focus (workspace,
+ window,
+ event->xkey.time);
+--
+1.6.5.rc2 \ No newline at end of file
diff --git a/cm-selection-timestamp.patch b/cm-selection-timestamp.patch
new file mode 100644
index 0000000..93da6dd
--- /dev/null
+++ b/cm-selection-timestamp.patch
@@ -0,0 +1,43 @@
+Patch from Travis Watkins
+https://bugzilla.gnome.org/show_bug.cgi?id=530702
+
+diff -ru metacity-2.27.0/src/core/screen.c metacity-2.27.0.new/src/core/screen.c
+--- metacity-2.27.0/src/core/screen.c 2008-10-19 16:15:38.000000000 -0500
++++ metacity-2.27.0.new/src/core/screen.c 2009-08-24 04:56:26.929023537 -0500
+@@ -2782,11 +2782,14 @@
+ char selection[32];
+ Atom a;
+
++ screen->wm_cm_timestamp = meta_display_get_current_time_roundtrip (
++ screen->display);
++
+ g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
+ meta_verbose ("Setting selection: %s\n", selection);
+ a = XInternAtom (screen->display->xdisplay, selection, FALSE);
+ XSetSelectionOwner (screen->display->xdisplay, a,
+- screen->wm_cm_selection_window, CurrentTime);
++ screen->wm_cm_selection_window, screen->wm_cm_timestamp);
+ }
+
+ void
+@@ -2797,6 +2800,7 @@
+
+ g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
+ a = XInternAtom (screen->display->xdisplay, selection, FALSE);
+- XSetSelectionOwner (screen->display->xdisplay, a, None, CurrentTime);
++ XSetSelectionOwner (screen->display->xdisplay, a,
++ None, screen->wm_cm_timestamp);
+ }
+ #endif /* HAVE_COMPOSITE_EXTENSIONS */
+diff -ru metacity-2.27.0/src/core/screen-private.h metacity-2.27.0.new/src/core/screen-private.h
+--- metacity-2.27.0/src/core/screen-private.h 2008-10-19 16:15:38.000000000 -0500
++++ metacity-2.27.0.new/src/core/screen-private.h 2009-08-24 04:50:41.469785283 -0500
+@@ -113,6 +113,7 @@
+
+ #ifdef HAVE_COMPOSITE_EXTENSIONS
+ Window wm_cm_selection_window;
++ guint32 wm_cm_timestamp;
+ #endif
+
+ guint work_area_idle;
+
diff --git a/metacity-2.28-empty-keybindings.patch b/metacity-2.28-empty-keybindings.patch
new file mode 100644
index 0000000..cc76a9b
--- /dev/null
+++ b/metacity-2.28-empty-keybindings.patch
@@ -0,0 +1,39 @@
+From 599f25e51d967febddb4de3aa21db4258356a9f9 Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Fri, 20 Nov 2009 10:19:03 -0500
+Subject: [PATCH] Accept an empty string as well as "disabled" for keybindings
+
+Treat the empty string the same as "disabled" for GConf keybinding
+keys. gnome-keybinding-properties was changed to write disabled
+keys as the empty string a year or so ago.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=559816
+---
+ src/ui/ui.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/ui/ui.c b/src/ui/ui.c
+index 6df289f..1e68df0 100644
+--- a/src/ui/ui.c
++++ b/src/ui/ui.c
+@@ -765,7 +765,7 @@ meta_ui_parse_accelerator (const char *accel,
+ *keycode = 0;
+ *mask = 0;
+
+- if (strcmp (accel, "disabled") == 0)
++ if (!accel[0] || strcmp (accel, "disabled") == 0)
+ return TRUE;
+
+ meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);
+@@ -852,7 +852,7 @@ meta_ui_parse_modifier (const char *accel,
+
+ *mask = 0;
+
+- if (accel == NULL || strcmp (accel, "disabled") == 0)
++ if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0)
+ return TRUE;
+
+ meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);
+--
+1.6.5.2
+
diff --git a/metacity-2.28-visual-bell.patch b/metacity-2.28-visual-bell.patch
new file mode 100644
index 0000000..bdc410c
--- /dev/null
+++ b/metacity-2.28-visual-bell.patch
@@ -0,0 +1,41 @@
+From 80bd3db7b6711c90af19c7ee17e86aea0b804d7c Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Fri, 20 Nov 2009 10:08:20 -0500
+Subject: [PATCH] Don't crash for visual bell on undecorated window
+
+When an XKB bell is sent on a undecorated window, flash the
+entire screen rather than crashing trying to flash the frame.
+
+Based on patch by Daniel Erat
+https://bugzilla.gnome.org/show_bug.cgi?id=598231
+---
+ src/core/bell.c | 7 ++++---
+ 1 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/bell.c b/src/core/bell.c
+index 1e01cd6..9904f97 100644
+--- a/src/core/bell.c
++++ b/src/core/bell.c
+@@ -231,15 +231,16 @@ bell_flash_frame (MetaDisplay *display,
+
+ g_assert (xkb_ev->xkb_type == XkbBellNotify);
+ window = meta_display_lookup_x_window (display, xkb_bell_event->window);
+- if (!window && (display->focus_window) && (display->focus_window->frame))
++ if (!window)
+ {
+ window = display->focus_window;
+ }
+- if (window)
++ if (window && window->frame)
+ {
+ bell_flash_window_frame (window);
+ }
+- else /* revert to fullscreen flash if there's no focussed window */
++ else /* revert to fullscreen flash if there's no focused window or if it
++ has no frame */
+ {
+ bell_flash_fullscreen (display, xkb_ev);
+ }
+--
+1.6.5.2
+
diff --git a/metacity-2.28-xioerror-unknown-display.patch b/metacity-2.28-xioerror-unknown-display.patch
new file mode 100644
index 0000000..2c29cd5
--- /dev/null
+++ b/metacity-2.28-xioerror-unknown-display.patch
@@ -0,0 +1,58 @@
+From 7c30ba2d034050e8e7d1776ea7541495bdf898b3 Mon Sep 17 00:00:00 2001
+From: Owen W. Taylor <otaylor@fishsoup.net>
+Date: Fri, 20 Nov 2009 10:42:07 -0500
+Subject: [PATCH] Handle XError and XIOError for unknown displays
+
+The atk-bridge GTK+ module opens its own display; if we get an
+XIOError on that display, we shouldn't abort with a meta_bug()
+but just exit normally. Also fix a segfault if we got an XError
+for that display.
+---
+ src/core/errors.c | 13 +++++--------
+ 1 files changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/src/core/errors.c b/src/core/errors.c
+index 8de4608..59f9c71 100644
+--- a/src/core/errors.c
++++ b/src/core/errors.c
+@@ -222,10 +222,10 @@ x_error_handler (Display *xdisplay,
+
+ display = meta_display_for_x_display (xdisplay);
+
+- /* Display can be NULL here because the compositing manager
+- * has its own Display, but Xlib only has one global error handler
++ /* Display can be NULL here Xlib only has one global error handler; and
++ * there might be other displays open in the process.
+ */
+- if (display->error_traps > 0)
++ if (display && display->error_traps > 0)
+ {
+ /* we're in an error trap, chain to the trap handler
+ * saved from GDK
+@@ -264,21 +264,18 @@ x_io_error_handler (Display *xdisplay)
+
+ display = meta_display_for_x_display (xdisplay);
+
+- if (display == NULL)
+- meta_bug ("IO error received for unknown display?\n");
+-
+ if (errno == EPIPE)
+ {
+ meta_warning (_("Lost connection to the display '%s';\n"
+ "most likely the X server was shut down or you killed/destroyed\n"
+ "the window manager.\n"),
+- display->name);
++ display ? display->name : DisplayString (xdisplay));
+ }
+ else
+ {
+ meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
+ errno, g_strerror (errno),
+- display->name);
++ display ? display->name : DisplayString (xdisplay));
+ }
+
+ /* Xlib would force an exit anyhow */
+--
+1.6.5.2
+
diff --git a/metacity.spec b/metacity.spec
index 604cf7d..eea0c4a 100644
--- a/metacity.spec
+++ b/metacity.spec
@@ -3,7 +3,7 @@
Summary: Unobtrusive window manager
Name: metacity
Version: 2.28.0
-Release: 11%{?dist}
+Release: 13%{?dist}
URL: http://download.gnome.org/sources/metacity/
Source0: http://download.gnome.org/sources/metacity/2.28/metacity-%{version}.tar.bz2
# http://bugzilla.gnome.org/show_bug.cgi?id=558723
@@ -28,6 +28,30 @@ Patch12: fresh-tooltips.patch
# https://bugzilla.gnome.org/show_bug.cgi?id=600864
# https://bugzilla.redhat.com/show_bug.cgi?id=533239
Patch13: metacity-dont-do-bad-stuff-on-sigterm.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=567528
+Patch14: Allow-explicit-raises-from-same-client-not-just-sa.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=445447
+Patch15: Allow-applications-to-raise-windows-when-raise_on_cl.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=598995
+Patch16: Dont-focus-ancestor-window-on-a-different-workspac.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=599262
+Patch17: Add-XFCE-Terminal-as-a-terminal.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=599097
+Patch18: For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=599248
+Patch19: Add-nofocuswindows-preference-to-list-windows-that.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=599261
+Patch20: Add-a-newwindowsalwaysontop-preference.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=577576
+Patch21: Dont-warn-about-a-missing-session-file.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=530702
+Patch22: cm-selection-timestamp.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=598231
+Patch23: metacity-2.28-visual-bell.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=559816
+Patch24: metacity-2.28-empty-keybindings.patch
+# https://bugzilla.gnome.org/show_bug.cgi?id=604319
+Patch25: metacity-2.28-xioerror-unknown-display.patch
License: GPLv2+
Group: User Interface/Desktops
@@ -55,7 +79,7 @@ BuildRequires: dbus-devel
BuildRequires: libcanberra-devel
Requires: startup-notification >= 0.7
-Requires: nodoka-metacity-theme
+Requires: gnome-themes
# for /usr/share/control-center/keybindings, /usr/share/gnome/wm-properties
Requires: control-center-filesystem
# for /etc/gconf/schemas
@@ -98,6 +122,19 @@ API. This package exists purely for technical reasons.
%patch12 -p1 -b .fresh-tooltips
%patch13 -p1 -b .sigterm
+%patch14 -p1 -b .raises-from-same-client
+%patch15 -p1 -b .raise-on-click-stacking
+%patch16 -p1 -b .focus-different-workspace
+%patch17 -p1 -b .xfce-terminal
+%patch18 -p1 -b .focus-on-motion
+%patch19 -p1 -b .no-focus-windows
+%patch20 -p1 -b .always-on-top
+%patch21 -p1 -b .missing-session
+%patch22 -p1 -b .cm-selection-timestamp
+%patch23 -p1 -b .visual-bell
+%patch24 -p1 -b .empty-keybindings
+%patch25 -p1 -b .xioerror-unknown-display
+
# force regeneration
rm src/metacity.schemas
@@ -204,6 +241,22 @@ fi
%{_mandir}/man1/metacity-window-demo.1.gz
%changelog
+* Thu Dec 10 2009 Owen Taylor <otaylor@redhat.com> - 2.28.0-12
+- Require gnome-themes rather than nodoka-metacity-theme (rhbz 532455, Stijn Hoop)
+- Add patches for GNOME bugs
+ 445447 - Application-induced window raise fails when raise_on_click off (rhbz 526045)
+ 530702 - compiz doesn't start if metacity compositor is enabled (rhbz 537791)
+ 559816 - Doesn't update keybindings being disabled/cleared (rhbz 532282)
+ 567528 - Cannot raise windows from applications in Tcl/Tk and Java (rhbz 503522)
+ 577576 - Failed to read saved session file warning on new sessions (rhbz 493245)
+ 598231 - When Chromium rings the bell, metacity quits(rhbz 532282)
+ 598995 - Don't focus ancestor window on a different workspace (rhbz 237158)
+ 599097 - For mouse and sloppy focus, return to "mouse mode" on motion (rhbz 530261)
+ 599248 - Add no_focus_windows preference to list windows that shouldn't be focused (rhbz 530262)
+ 599261 - Add a new_windows_always_on_top preference (rhbz 530263)
+ 599262 - Add XFCE Terminal as a terminal
+ 604319 - XIOError unknown display (rhbz 537845)
+
* Thu Nov 26 2009 Matthias Clasen <mclasen@redhat.com> - 2.28.0-11
- Fix a problem with the previous change