From 97b03230fda37fecb08ffb38d83e33d4c86aa7be Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Thu, 10 Dec 2009 23:33:00 +0000 Subject: - 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 | 28 + Add-a-newwindowsalwaysontop-preference.patch | 155 ++++ ...uswindows-preference-to-list-windows-that.patch | 862 +++++++++++++++++++++ ...cations-to-raise-windows-when-raise_on_cl.patch | 31 + ...licit-raises-from-same-client-not-just-sa.patch | 73 ++ ...s-ancestor-window-on-a-different-workspac.patch | 39 + Dont-warn-about-a-missing-session-file.patch | 36 + ...-and-sloppy-focus-return-to-mouse-mode-on.patch | 394 ++++++++++ cm-selection-timestamp.patch | 43 + metacity-2.28-empty-keybindings.patch | 39 + metacity-2.28-visual-bell.patch | 41 + metacity-2.28-xioerror-unknown-display.patch | 58 ++ metacity.spec | 57 +- 13 files changed, 1854 insertions(+), 2 deletions(-) create mode 100644 Add-XFCE-Terminal-as-a-terminal.patch create mode 100644 Add-a-newwindowsalwaysontop-preference.patch create mode 100644 Add-nofocuswindows-preference-to-list-windows-that.patch create mode 100644 Allow-applications-to-raise-windows-when-raise_on_cl.patch create mode 100644 Allow-explicit-raises-from-same-client-not-just-sa.patch create mode 100644 Dont-focus-ancestor-window-on-a-different-workspac.patch create mode 100644 Dont-warn-about-a-missing-session-file.patch create mode 100644 For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch create mode 100644 cm-selection-timestamp.patch create mode 100644 metacity-2.28-empty-keybindings.patch create mode 100644 metacity-2.28-visual-bell.patch create mode 100644 metacity-2.28-xioerror-unknown-display.patch 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 +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 +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 @@ + + + ++ /schemas/apps/metacity/general/new_windows_always_on_top ++ /apps/metacity/general/new_windows_always_on_top ++ metacity ++ bool ++ false ++ ++ Whether new windows should always be placed on top ++ ++ 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. ++ ++ ++ ++ ++ + /schemas/apps/metacity/general/action_double_click_titlebar + /apps/metacity/general/action_double_click_titlebar + metacity +-- +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 +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 + #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 ++#include ++ ++#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 ) ++ * (or ) ++ * (not ) ++ * (eq [name|class] "") ++ * (glob [name|class] "") ++ * ++ * 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 @@ + + + ++ /schemas/apps/metacity/general/no_focus_windows ++ /apps/metacity/general/no_focus_windows ++ metacity ++ string ++ ++ ++ New windows that shouldn't get focus ++ ++ 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. ++ ++ ++ ++ ++ + /schemas/apps/metacity/general/raise_on_click + /apps/metacity/general/raise_on_click + metacity 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 +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 +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 ++#include /* For display->resource_mask */ + #include + + #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 +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 +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 +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 +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 +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 +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 - 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 - 2.28.0-11 - Fix a problem with the previous change -- cgit