rpms/metacity/devel Add-XFCE-Terminal-as-a-terminal.patch, NONE, 1.1 Add-a-newwindowsalwaysontop-preference.patch, NONE, 1.1 Add-nofocuswindows-preference-to-list-windows-that.patch, NONE, 1.1 Allow-applications-to-raise-windows-when-raise_on_cl.patch, NONE, 1.1 Allow-explicit-raises-from-same-client-not-just-sa.patch, NONE, 1.1 Dont-focus-ancestor-window-on-a-different-workspac.patch, NONE, 1.1 Dont-warn-about-a-missing-session-file.patch, NONE, 1.1 For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch, NONE, 1.1 cm-selection-timestamp.patch, NONE, 1.1 metacity-2.28-empty-keybindings.patch, NONE, 1.1 metacity-2.28-visual-bell.patch, NONE, 1.1 metacity-2.28-xioerror-unknown-display.patch, NONE, 1.1 metacity.spec, 1.205, 1.206

Owen Taylor otaylor at fedoraproject.org
Thu Dec 10 23:33:00 UTC 2009


Author: otaylor

Update of /cvs/extras/rpms/metacity/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv24443

Modified Files:
	metacity.spec 
Added Files:
	Add-XFCE-Terminal-as-a-terminal.patch 
	Add-a-newwindowsalwaysontop-preference.patch 
	Add-nofocuswindows-preference-to-list-windows-that.patch 
	Allow-applications-to-raise-windows-when-raise_on_cl.patch 
	Allow-explicit-raises-from-same-client-not-just-sa.patch 
	Dont-focus-ancestor-window-on-a-different-workspac.patch 
	Dont-warn-about-a-missing-session-file.patch 
	For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch 
	cm-selection-timestamp.patch 
	metacity-2.28-empty-keybindings.patch 
	metacity-2.28-visual-bell.patch 
	metacity-2.28-xioerror-unknown-display.patch 
Log Message:
* Thu Dec 10 2009 Owen Taylor <otaylor at 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)


Add-XFCE-Terminal-as-a-terminal.patch:
 window.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- NEW FILE Add-XFCE-Terminal-as-a-terminal.patch ---
>From bf7327acb41a43b2bdeee9f0855455ebaef8b816 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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
Add-a-newwindowsalwaysontop-preference.patch:
 core/prefs.c           |   17 ++++++++++++++++-
 core/window.c          |    6 +++++-
 include/prefs.h        |    2 ++
 metacity.schemas.in.in |   30 +++++++++++++++++++++++++++++-
 4 files changed, 52 insertions(+), 3 deletions(-)

--- NEW FILE Add-a-newwindowsalwaysontop-preference.patch ---
>From c4fba8198bacc8ecf911cb15c9cd9314f3204a85 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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


Add-nofocuswindows-preference-to-list-windows-that.patch:
 Makefile.am            |    2 
 core/prefs.c           |   43 +++
 core/window-matcher.c  |  582 +++++++++++++++++++++++++++++++++++++++++++++++++
 core/window-matcher.h  |   46 +++
 core/window.c          |    9 
 include/prefs.h        |    6 
 metacity.schemas.in.in |   28 ++
 7 files changed, 714 insertions(+), 2 deletions(-)

--- NEW FILE Add-nofocuswindows-preference-to-list-windows-that.patch ---
>From 88c66808ec5f2bfba425fc6d6f0b9ac43ed44696 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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] "<value>"): window name (title) or the class from
+	    WM_CLASS matches <value> exactly.
+	    (glob [name|class] "<glob>"): window name (title) or the class from
+	    WM_CLASS matches the shell-style glob pattern <glob>.
+	    (and <expr> <expr>) (or <expr> <expr>) (not <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>

Allow-applications-to-raise-windows-when-raise_on_cl.patch:
 window.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

--- NEW FILE Allow-applications-to-raise-windows-when-raise_on_cl.patch ---
>From 55d4c4cc9455f348b5bc455675004a0e035ea31d Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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


Allow-explicit-raises-from-same-client-not-just-sa.patch:
 window.c |   23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

--- NEW FILE Allow-explicit-raises-from-same-client-not-just-sa.patch ---
>From 7e116a394689718567406837740679c1f1f0d74f Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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
Dont-focus-ancestor-window-on-a-different-workspac.patch:
 workspace.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

--- NEW FILE Dont-focus-ancestor-window-on-a-different-workspac.patch ---
>From a17fb47e08257d09e1e795e8114b21b134b1f3c2 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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
Dont-warn-about-a-missing-session-file.patch:
 session.c |    3 ---
 1 file changed, 3 deletions(-)

--- NEW FILE Dont-warn-about-a-missing-session-file.patch ---
>From 3b06d1045cc990a8610bdbd5c9b83440b1b6e932 Mon Sep 17 00:00:00 2001
From: Tomislav Vujec <tvujec at 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
For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch:
 display-private.h |   11 ++
 display.c         |  239 +++++++++++++++++++++++++++++++++++++++++++-----------
 keybindings.c     |   11 +-
 3 files changed, 210 insertions(+), 51 deletions(-)

--- NEW FILE For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch ---
>From e8a6af29a1f57024067a12567e2bd906e6bad5a4 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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
cm-selection-timestamp.patch:
 screen-private.h |    1 +
 screen.c         |    8 ++++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

--- NEW FILE cm-selection-timestamp.patch ---
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;


metacity-2.28-empty-keybindings.patch:
 ui.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

--- NEW FILE metacity-2.28-empty-keybindings.patch ---
>From 599f25e51d967febddb4de3aa21db4258356a9f9 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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


metacity-2.28-visual-bell.patch:
 bell.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- NEW FILE metacity-2.28-visual-bell.patch ---
>From 80bd3db7b6711c90af19c7ee17e86aea0b804d7c Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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


metacity-2.28-xioerror-unknown-display.patch:
 errors.c |   14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

--- NEW FILE metacity-2.28-xioerror-unknown-display.patch ---
>From 7c30ba2d034050e8e7d1776ea7541495bdf898b3 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <otaylor at 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



Index: metacity.spec
===================================================================
RCS file: /cvs/extras/rpms/metacity/devel/metacity.spec,v
retrieving revision 1.205
retrieving revision 1.206
diff -u -p -r1.205 -r1.206
--- metacity.spec	26 Nov 2009 08:56:04 -0000	1.205
+++ metacity.spec	10 Dec 2009 23:33:00 -0000	1.206
@@ -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 tech
 %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 at 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 at redhat.com> - 2.28.0-11
 - Fix a problem with the previous change
 




More information about the fedora-extras-commits mailing list