From 14ad8e85309338a4fe8ac305fa1546ba1b4ec966 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Oct 31 2019 10:09:18 +0000 Subject: import metacity-2.34.13-7.el7 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..623e121 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/metacity-2.34.13.tar.xz diff --git a/.metacity.metadata b/.metacity.metadata new file mode 100644 index 0000000..afa21dd --- /dev/null +++ b/.metacity.metadata @@ -0,0 +1 @@ +7b5b20e84ffb86290955a726af946a78b7a45e26 SOURCES/metacity-2.34.13.tar.xz diff --git a/SOURCES/0001-doc-Update-man-pages.patch b/SOURCES/0001-doc-Update-man-pages.patch new file mode 100644 index 0000000..9b7adcb --- /dev/null +++ b/SOURCES/0001-doc-Update-man-pages.patch @@ -0,0 +1,94 @@ +From 90dc810b9f501136c6f1cf94bc4f4c1f626412b9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 16 May 2013 15:37:43 +0200 +Subject: [PATCH] doc: Update man pages + +Metacity is not the fastest moving project, however there were +a view additions in the last nine years, document those. +--- + doc/man/metacity-message.1 | 13 +++++++++++-- + doc/man/metacity.1 | 16 ++++++++++++++-- + 2 files changed, 25 insertions(+), 4 deletions(-) + +diff --git a/doc/man/metacity-message.1 b/doc/man/metacity-message.1 +index 80041f5..13839f8 100644 +--- a/doc/man/metacity-message.1 ++++ b/doc/man/metacity-message.1 +@@ -12,7 +12,7 @@ + .\" > Right I know. any licenses that is DFSG-free, I'm ok with whatever, + .\" > since I have contributed that for Debian. so GPL is no problem for me. + .\" ----- +-.TH METACITY\-MESSAGE 1 "28 August 2002" ++.TH METACITY\-MESSAGE 1 "16 May 2013" + .\" Please adjust this date whenever revising the manpage. + .\" + .\" Some roff macros, for reference: +@@ -29,7 +29,7 @@ + METACITY\-MESSAGE \- a command to send a message to Metacity + .SH SYNOPSIS + .B METACITY\-MESSAGE +-[restart|reload\-theme|enable\-keybindings|disable\-keybindings] ++[restart|reload\-theme|enable\-keybindings|disable\-keybindings|enable\-mouse\-button\-modifiers|disable\-mouse\-button\-modifiers|toggle\-verbose] + .SH DESCRIPTION + This manual page documents briefly the + .B metacity\-message\fP. +@@ -53,6 +53,15 @@ Enable all of keybindings which is specified on gsettings database. + .TP + .B disable-keybindings + Disable all of keybindings which is specified on gsettings database. ++.TP ++.B enable-mouse-button-modifiers ++Enable move/resize operations while pressing a modifier key ++.TP ++.B disable-mouse-button-modifiers ++Disable move/resize operations while pressing a modifier key ++.TP ++.B toggle-verbose ++Turn debug messages on or off + .SH SEE ALSO + .BR metacity (1) + .SH AUTHOR +diff --git a/doc/man/metacity.1 b/doc/man/metacity.1 +index 0a4c347..eaf75b5 100644 +--- a/doc/man/metacity.1 ++++ b/doc/man/metacity.1 +@@ -2,7 +2,7 @@ + .\" First parameter, NAME, should be all caps + .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection + .\" other parameters are allowed: see man(7), man(1) +-.TH METACITY 1 "11 February 2006" ++.TH METACITY 1 "16 May 2013" + .\" Please adjust this date whenever revising the manpage. + .\" + .\" Some roff macros, for reference: +@@ -19,7 +19,7 @@ + METACITY \- minimal GTK2 Window Manager + .SH SYNOPSIS + .B metacity +-[\-\-display=\fIDISPLAY\fP] [\-\-replace] [\-\-sm\-client\-id=\fIID\fP] [\-\-sm\-disable] [\-\-sm\-save\-file=\fIFILENAME\fP] [\-\-version] [\-\-help] ++[\-\-display=\fIDISPLAY\fP] [\-\-replace] [\-\-sm\-client\-id=\fIID\fP] [\-\-sm\-disable] [\-\-sm\-save\-file=\fIFILENAME\fP] [\-\-sync] [\-\-composite] [\-\-no-composite] [\-\-no-force-fullscreen] [\-\-version] [\-\-help] + .SH DESCRIPTION + This manual page documents briefly + .B metacity\fP. +@@ -45,6 +45,18 @@ Disable the session management. + .B \-\-sm\-save\-file=FILENAME + Load a session from \fIFILENAME\fP. + .TP ++.B \-\-sync ++Make X calls synchronous ++.TP ++.B \-\-composite ++Turn compositing on ++.TP ++.B \-\-no-composite ++Turn compositing off ++.TP ++.B \-\-no-force-fullscreen ++Don't make fullscreen windows that are maximized and have no decorations ++.TP + .B \-\-version + Print the version number. + .TP +-- +1.8.2.1 + diff --git a/SOURCES/Add-a-newwindowsalwaysontop-preference.patch b/SOURCES/Add-a-newwindowsalwaysontop-preference.patch new file mode 100644 index 0000000..f3bf1b1 --- /dev/null +++ b/SOURCES/Add-a-newwindowsalwaysontop-preference.patch @@ -0,0 +1,160 @@ +From 861a3efb0f531eae767926d18c4d690366306bfe 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 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 | 20 +++++++++++++++++++- + src/core/window.c | 6 +++++- + src/include/prefs.h | 2 ++ + src/metacity-schemas.convert | 1 + + src/org.gnome.metacity.gschema.xml.in | 22 ++++++++++++++++++++++ + 5 files changed, 49 insertions(+), 2 deletions(-) + +diff --git a/src/core/prefs.c b/src/core/prefs.c +index 24a98cd..949f6ed 100644 +--- a/src/core/prefs.c ++++ b/src/core/prefs.c +@@ -73,6 +73,7 @@ static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK; + static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_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 GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE; +@@ -261,6 +262,14 @@ static MetaBoolPreference preferences_bool[] = + TRUE, + }, + { ++ { "new-windows-always-on-top", ++ SCHEMA_METACITY, ++ META_PREF_NEW_WINDOWS_ALWAYS_ON_TOP, ++ }, ++ &new_windows_always_on_top, ++ TRUE, ++ }, ++ { + { "titlebar-uses-system-font", + SCHEMA_GENERAL, + META_PREF_TITLEBAR_FONT, /* note! shares a pref */ +@@ -920,6 +929,12 @@ meta_prefs_get_raise_on_click (void) + return raise_on_click || focus_mode == G_DESKTOP_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) + { +@@ -1386,7 +1401,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 6f5c280..b6a69b0 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -2008,7 +2008,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 +@@ -2055,6 +2055,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 b86843c..c49e93d 100644 +--- a/src/include/prefs.h ++++ b/src/include/prefs.h +@@ -37,6 +37,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); + GDesktopFocusMode meta_prefs_get_focus_mode (void); + GDesktopFocusNewWindows 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.convert b/src/metacity-schemas.convert +index 9c271c6..f1fce08 100644 +--- a/src/metacity-schemas.convert ++++ b/src/metacity-schemas.convert +@@ -2,3 +2,4 @@ + compositing-manager = /apps/metacity/general/compositing_manager + reduced-resources = /apps/metacity/general/reduced_resources + no-focus-windows = /apps/metacity/general/no_focus_windows ++new-windows-always-on-top = /apps/metacity/general/new_windows_always_on_top +diff --git a/src/org.gnome.metacity.gschema.xml.in b/src/org.gnome.metacity.gschema.xml.in +index e4f86bd..d69d525 100644 +--- a/src/org.gnome.metacity.gschema.xml.in ++++ b/src/org.gnome.metacity.gschema.xml.in +@@ -46,6 +46,28 @@ + this setting. + + ++ ++ false ++ <_summary>Whether new windows should always be placed on top ++ <_description> ++ 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. ++ ++ + + + +-- +1.7.9 + diff --git a/SOURCES/Add-nofocuswindows-preference-to-list-windows-that.patch b/SOURCES/Add-nofocuswindows-preference-to-list-windows-that.patch new file mode 100644 index 0000000..bca6f10 --- /dev/null +++ b/SOURCES/Add-nofocuswindows-preference-to-list-windows-that.patch @@ -0,0 +1,881 @@ +From 60d38a7c6683001ee2beb72b8f0b0beee4f04bb4 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: + + 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 | 55 +++ + 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.convert | 1 + + src/org.gnome.metacity.gschema.xml.in | 21 ++ + 8 files changed, 720 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 4d405bf..2befe33 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -66,6 +66,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 58f11e9..24a98cd 100644 +--- a/src/core/prefs.c ++++ b/src/core/prefs.c +@@ -26,6 +26,7 @@ + + #include + #include "prefs.h" ++#include "window-matcher.h" + #include "ui.h" + #include "util.h" + #include +@@ -70,6 +71,7 @@ static PangoFontDescription *titlebar_font = NULL; + static MetaVirtualModifier mouse_button_mods = Mod1Mask; + static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK; + static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_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; +@@ -120,6 +122,7 @@ static void maybe_give_disable_workarounds_warning (void); + + static gboolean titlebar_handler (GVariant*, gpointer*, gpointer); + static gboolean theme_name_handler (GVariant*, gpointer*, gpointer); ++static gboolean no_focus_windows_handler (GVariant*, gpointer*, gpointer); + static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer); + static gboolean button_layout_handler (GVariant*, gpointer*, gpointer); + +@@ -367,6 +370,14 @@ static MetaStringPreference preferences_string[] = + NULL, + }, + { ++ { "no-focus-windows", ++ SCHEMA_METACITY, ++ META_PREF_NO_FOCUS_WINDOWS, ++ }, ++ no_focus_windows_handler, ++ NULL ++ }, ++ { + { KEY_TITLEBAR_FONT, + SCHEMA_GENERAL, + META_PREF_TITLEBAR_FONT, +@@ -998,6 +1009,39 @@ theme_name_handler (GVariant *value, + } + + static gboolean ++no_focus_windows_handler (GVariant *value, ++ gpointer *result, ++ gpointer data) ++{ ++ const gchar *string_value; ++ ++ *result = NULL; /* ignored */ ++ string_value = g_variant_get_string (value, NULL); ++ ++ 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); ++ ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean + mouse_button_mods_handler (GVariant *value, + gpointer *result, + gpointer data) +@@ -1414,6 +1458,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)"; +@@ -1710,6 +1757,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..df889eb +--- /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 ((MatcherToken) 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 ((MatcherToken) token != MATCHER_TOKEN_NOT) ++ { ++ b = meta_window_matcher_from_scanner (scanner, error); ++ if (!b) ++ { ++ meta_window_matcher_free (a); ++ return NULL; ++ } ++ } ++ ++ switch ((MatcherToken) 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 ((MatcherToken) 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 ((MatcherToken) 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 2f2f800..5440160 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -1981,7 +1981,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 673cb36..b86843c 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, +@@ -105,6 +106,9 @@ GDesktopTitlebarAction meta_prefs_get_action_double_click_titlebar (void); + GDesktopTitlebarAction meta_prefs_get_action_middle_click_titlebar (void); + GDesktopTitlebarAction 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.convert b/src/metacity-schemas.convert +index 46f3104..9c271c6 100644 +--- a/src/metacity-schemas.convert ++++ b/src/metacity-schemas.convert +@@ -1,3 +1,4 @@ + [org.gnome.metacity] + compositing-manager = /apps/metacity/general/compositing_manager + reduced-resources = /apps/metacity/general/reduced_resources ++no-focus-windows = /apps/metacity/general/no_focus_windows +diff --git a/src/org.gnome.metacity.gschema.xml.in b/src/org.gnome.metacity.gschema.xml.in +index 8fcdd7c..6900fa6 100644 +--- a/src/org.gnome.metacity.gschema.xml.in ++++ b/src/org.gnome.metacity.gschema.xml.in +@@ -22,6 +22,27 @@ + However, the wireframe feature is disabled when accessibility is on. + + ++ ++ '' ++ <_summary>New windows that shouldn't get focus ++ <_description> ++ 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. ++ ++ + + + +-- +1.7.9 + diff --git a/SOURCES/Allow-breaking-out-from-maximization-during-mouse.patch b/SOURCES/Allow-breaking-out-from-maximization-during-mouse.patch new file mode 100644 index 0000000..286c873 --- /dev/null +++ b/SOURCES/Allow-breaking-out-from-maximization-during-mouse.patch @@ -0,0 +1,414 @@ +From 00d291927a59b6bca164fc5cd2d4729604b40d1c Mon Sep 17 00:00:00 2001 +From: "Owen W. Taylor" +Date: Wed, 23 Jun 2010 15:08:38 -0400 +Subject: [PATCH] Allow breaking out from maximization during a mouse + resize + +A maximized window can't be resized from the screen edges (preserves +Fitts law goodness for the application), but it's still possible +to start a resize drag with alt-middle-button. Currently we just +don't let the user resize the window, while showing drag feedback; +it's more useful to let the user "break" out from the resize. + +This provides a fast way to get a window partially aligned with +the screen edges - maximize, then alt-drag it out from one edge. + +Behavior choices in this patch: + + - You can drag out a window out of maximization in both directions - + smaller and larger. This can be potentilaly useful in multihead. + + - Dragging a window in only one direction unmaximizes the window + fully, rather than leaving it in a horizontally/vertically + maximized state. This is done because the horizontally/vertically + maximzed states don't have clear visual representation and can + be confusing to the user. + + - If you drag back to the maximized state after breaking out, + maximization is restored, but you can't maximize a window by + dragging to the full size if it didn't start out that way. + +A new internal function meta_window_unmaximize_with_gravity() is +added for implementing this; it's a hybrid of +meta_window_unmaximize() and meta_window_resize_with_gravity(). + +https://bugzilla.gnome.org/show_bug.cgi?id=622517 +--- + src/core/display-private.h | 3 + + src/core/display.c | 20 +++- + src/core/window-private.h | 5 + + src/core/window.c | 224 ++++++++++++++++++++++++++++++++++++++++---- + 4 files changed, 228 insertions(+), 24 deletions(-) + +diff --git a/src/core/display-private.h b/src/core/display-private.h +index 7f779fd..bb6ba8a 100644 +--- a/src/core/display-private.h ++++ b/src/core/display-private.h +@@ -178,6 +178,9 @@ struct _MetaDisplay + guint grab_wireframe_active : 1; + guint grab_was_cancelled : 1; /* Only used in wireframe mode */ + guint grab_frame_action : 1; ++ /* During a resize operation, the directions in which we've broken ++ * out of the initial maximization state */ ++ guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */ + MetaRectangle grab_wireframe_rect; + MetaRectangle grab_wireframe_last_xor_rect; + MetaRectangle grab_initial_window_pos; +diff --git a/src/core/display.c b/src/core/display.c +index 0c5f61d..25cf857 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -3470,6 +3470,7 @@ meta_display_begin_grab_op (MetaDisplay *display, + #endif + display->grab_was_cancelled = FALSE; + display->grab_frame_action = frame_action; ++ display->grab_resize_unmaximize = 0; + + if (display->grab_resize_timeout_id) + { +@@ -3700,11 +3701,20 @@ meta_display_end_grab_op (MetaDisplay *display, + display->grab_wireframe_rect.x, + display->grab_wireframe_rect.y); + if (meta_grab_op_is_resizing (display->grab_op)) +- meta_window_resize_with_gravity (display->grab_window, +- TRUE, +- display->grab_wireframe_rect.width, +- display->grab_wireframe_rect.height, +- meta_resize_gravity_from_grab_op (display->grab_op)); ++ { ++ if (display->grab_resize_unmaximize != 0) ++ meta_window_unmaximize_with_gravity (display->grab_window, ++ display->grab_resize_unmaximize, ++ display->grab_wireframe_rect.width, ++ display->grab_wireframe_rect.height, ++ meta_resize_gravity_from_grab_op (display->grab_op)); ++ else ++ meta_window_resize_with_gravity (display->grab_window, ++ TRUE, ++ display->grab_wireframe_rect.width, ++ display->grab_wireframe_rect.height, ++ meta_resize_gravity_from_grab_op (display->grab_op)); ++ } + } + meta_window_calc_showing (display->grab_window); + } +diff --git a/src/core/window-private.h b/src/core/window-private.h +index 7cf5b04..2c07e85 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -412,6 +412,11 @@ void meta_window_maximize_internal (MetaWindow *window, + MetaRectangle *saved_rect); + void meta_window_unmaximize (MetaWindow *window, + MetaMaximizeFlags directions); ++void meta_window_unmaximize_with_gravity (MetaWindow *window, ++ MetaMaximizeFlags directions, ++ int new_width, ++ int new_height, ++ int gravity); + void meta_window_make_above (MetaWindow *window); + void meta_window_unmake_above (MetaWindow *window); + void meta_window_shade (MetaWindow *window, +diff --git a/src/core/window.c b/src/core/window.c +index 897161e..427f91f 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -2693,9 +2693,11 @@ unmaximize_window_before_freeing (MetaWindow *window) + } + } + +-void +-meta_window_unmaximize (MetaWindow *window, +- MetaMaximizeFlags directions) ++static void ++meta_window_unmaximize_internal (MetaWindow *window, ++ MetaMaximizeFlags directions, ++ MetaRectangle *desired_rect, ++ int gravity) + { + /* At least one of the two directions ought to be set */ + gboolean unmaximize_horizontally, unmaximize_vertically; +@@ -2729,13 +2731,13 @@ meta_window_unmaximize (MetaWindow *window, + meta_window_get_client_root_coords (window, &target_rect); + if (unmaximize_horizontally) + { +- target_rect.x = window->saved_rect.x; +- target_rect.width = window->saved_rect.width; ++ target_rect.x = desired_rect->x; ++ target_rect.width = desired_rect->width; + } + if (unmaximize_vertically) + { +- target_rect.y = window->saved_rect.y; +- target_rect.height = window->saved_rect.height; ++ target_rect.y = desired_rect->y; ++ target_rect.height = desired_rect->height; + } + + /* Window's size hints may have changed while maximized, making +@@ -2754,12 +2756,13 @@ meta_window_unmaximize (MetaWindow *window, + window->display->grab_anchor_window_pos = target_rect; + } + +- meta_window_move_resize (window, +- FALSE, +- target_rect.x, +- target_rect.y, +- target_rect.width, +- target_rect.height); ++ meta_window_move_resize_internal (window, ++ META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION, ++ gravity, ++ target_rect.x, ++ target_rect.y, ++ target_rect.width, ++ target_rect.height); + + /* Make sure user_rect is current. + */ +@@ -2776,6 +2779,36 @@ meta_window_unmaximize (MetaWindow *window, + } + + void ++meta_window_unmaximize (MetaWindow *window, ++ MetaMaximizeFlags directions) ++{ ++ meta_window_unmaximize_internal (window, directions, &window->saved_rect, ++ NorthWestGravity); ++} ++ ++/* Like meta_window_unmaximize(), but instead of unmaximizing to the ++ * saved position, we give the new desired size, and the gravity that ++ * determines the positioning relationship between the area occupied ++ * maximized and the new are. The arguments are similar to ++ * meta_window_resize_with_gravity(). ++ */ ++void ++meta_window_unmaximize_with_gravity (MetaWindow *window, ++ MetaMaximizeFlags directions, ++ int new_width, ++ int new_height, ++ int gravity) ++{ ++ MetaRectangle desired_rect; ++ ++ meta_window_get_position (window, &desired_rect.x, &desired_rect.y); ++ desired_rect.width = new_width; ++ desired_rect.height = new_height; ++ ++ meta_window_unmaximize_internal (window, directions, &desired_rect, gravity); ++} ++ ++void + meta_window_make_above (MetaWindow *window) + { + window->wm_state_above = TRUE; +@@ -7124,6 +7157,112 @@ update_resize_timeout (gpointer data) + return FALSE; + } + ++/* When resizing a maximized window by using alt-middle-drag (resizing ++ * with the grips or the menu for a maximized window is not enabled), ++ * the user can "break" out of the maximized state. This checks for ++ * that possibility. During such a break-out resize the user can also ++ * return to the previous maximization state by resizing back to near ++ * the original size. ++ */ ++static MetaMaximizeFlags ++check_resize_unmaximize(MetaWindow *window, ++ int dx, ++ int dy) ++{ ++ int threshold; ++ MetaMaximizeFlags new_unmaximize; ++ ++#define DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR 3 ++ ++ threshold = meta_ui_get_drag_threshold (window->screen->ui) * ++ DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR; ++ new_unmaximize = 0; ++ ++ if (window->maximized_horizontally || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) ++ { ++ int x_amount; ++ ++ /* We allow breaking out of maximization in either direction, to make ++ * the window larger than the monitor as well as smaller than the ++ * monitor. If we wanted to only allow resizing smaller than the ++ * monitor, we'd use - dx for NE/E/SE and dx for SW/W/NW. ++ */ ++ switch (window->display->grab_op) ++ { ++ case META_GRAB_OP_RESIZING_NE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NE: ++ case META_GRAB_OP_RESIZING_E: ++ case META_GRAB_OP_KEYBOARD_RESIZING_E: ++ case META_GRAB_OP_RESIZING_SE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SE: ++ case META_GRAB_OP_RESIZING_SW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SW: ++ case META_GRAB_OP_RESIZING_W: ++ case META_GRAB_OP_KEYBOARD_RESIZING_W: ++ case META_GRAB_OP_RESIZING_NW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NW: ++ x_amount = dx < 0 ? - dx : dx; ++ break; ++ default: ++ x_amount = 0; ++ break; ++ } ++ ++ if (x_amount > threshold) ++ new_unmaximize |= META_MAXIMIZE_HORIZONTAL; ++ } ++ ++ if (window->maximized_vertically || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) ++ { ++ int y_amount; ++ ++ switch (window->display->grab_op) ++ { ++ case META_GRAB_OP_RESIZING_N: ++ case META_GRAB_OP_KEYBOARD_RESIZING_N: ++ case META_GRAB_OP_RESIZING_NE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NE: ++ case META_GRAB_OP_RESIZING_NW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NW: ++ case META_GRAB_OP_RESIZING_SE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SE: ++ case META_GRAB_OP_RESIZING_S: ++ case META_GRAB_OP_KEYBOARD_RESIZING_S: ++ case META_GRAB_OP_RESIZING_SW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SW: ++ y_amount = dy < 0 ? - dy : dy; ++ break; ++ default: ++ y_amount = 0; ++ break; ++ } ++ ++ if (y_amount > threshold) ++ new_unmaximize |= META_MAXIMIZE_VERTICAL; ++ } ++ ++ /* Metacity doesn't have a full user interface for only horizontally or ++ * vertically maximized, so while only unmaximizing in the direction drags ++ * has some advantages, it will also confuse the user. So, we always ++ * unmaximize both ways if possible. ++ */ ++ if (new_unmaximize != 0) ++ { ++ new_unmaximize = 0; ++ ++ if (window->maximized_horizontally || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) ++ new_unmaximize |= META_MAXIMIZE_HORIZONTAL; ++ if (window->maximized_vertically || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) ++ new_unmaximize |= META_MAXIMIZE_VERTICAL; ++ } ++ ++ return new_unmaximize; ++} ++ + static void + update_resize (MetaWindow *window, + gboolean snap, +@@ -7136,6 +7275,7 @@ update_resize (MetaWindow *window, + MetaRectangle old; + int new_x, new_y; + double remaining; ++ MetaMaximizeFlags new_unmaximize; + + window->display->grab_latest_motion_x = x; + window->display->grab_latest_motion_y = y; +@@ -7200,7 +7340,9 @@ update_resize (MetaWindow *window, + meta_window_update_keyboard_resize (window, TRUE); + } + } +- ++ ++ new_unmaximize = check_resize_unmaximize (window, dx, dy); ++ + /* FIXME: This stupidity only needed because of wireframe mode and + * the fact that wireframe isn't making use of + * meta_rectangle_resize_with_gravity(). If we were to use that, we +@@ -7324,6 +7466,8 @@ update_resize (MetaWindow *window, + + if (window->display->grab_wireframe_active) + { ++ MetaRectangle root_coords; ++ + if ((new_x + new_w <= new_x) || (new_y + new_h <= new_y)) + return; + +@@ -7333,18 +7477,60 @@ update_resize (MetaWindow *window, + * wireframe, but still resize it; however, that probably + * confuses broken clients that have problems with opaque + * resize, they probably don't track their visibility. ++ * ++ * We handle the basic constraints on maximized windows here ++ * to give the user feedback. + */ ++ ++ if (window->maximized_horizontally && (new_unmaximize & META_MAXIMIZE_HORIZONTAL) == 0) ++ { ++ meta_window_get_client_root_coords (window, &root_coords); ++ new_x = root_coords.x; ++ new_w = root_coords.width; ++ } ++ if (window->maximized_vertically && (new_unmaximize & META_MAXIMIZE_VERTICAL) == 0) ++ { ++ meta_window_get_client_root_coords (window, &root_coords); ++ new_y = root_coords.y; ++ new_h = root_coords.height; ++ } ++ + meta_window_update_wireframe (window, new_x, new_y, new_w, new_h); + } + else + { +- /* We don't need to update unless the specified width and height +- * are actually different from what we had before. +- */ +- if (old.width != new_w || old.height != new_h) +- meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); ++ if (new_unmaximize == window->display->grab_resize_unmaximize) ++ { ++ /* We don't need to update unless the specified width and height ++ * are actually different from what we had before. ++ */ ++ if (old.width != new_w || old.height != new_h) ++ { ++ if ((window->display->grab_resize_unmaximize == new_unmaximize)) ++ meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); ++ } ++ } ++ else ++ { ++ if ((new_unmaximize & ~window->display->grab_resize_unmaximize) != 0) ++ { ++ meta_window_unmaximize_with_gravity (window, ++ (new_unmaximize & ~window->display->grab_resize_unmaximize), ++ new_w, new_h, gravity); ++ } ++ ++ if ((window->display->grab_resize_unmaximize & ~new_unmaximize)) ++ { ++ MetaRectangle saved_rect = window->saved_rect; ++ meta_window_maximize (window, ++ (window->display->grab_resize_unmaximize & ~new_unmaximize)); ++ window->saved_rect = saved_rect; ++ } ++ } + } + ++ window->display->grab_resize_unmaximize = new_unmaximize; ++ + /* Store the latest resize time, if we actually resized. */ + if (window->rect.width != old.width || window->rect.height != old.height) + g_get_current_time (&window->display->grab_last_moveresize_time); +-- +1.7.9 + diff --git a/SOURCES/Apply-new_windows_always_on_top-to-newly-raised-acti.patch b/SOURCES/Apply-new_windows_always_on_top-to-newly-raised-acti.patch new file mode 100644 index 0000000..93378bf --- /dev/null +++ b/SOURCES/Apply-new_windows_always_on_top-to-newly-raised-acti.patch @@ -0,0 +1,113 @@ +From 2bd938c957b27c1055f7f235939c9b8b338d5cbf Mon Sep 17 00:00:00 2001 +From: "Owen W. Taylor" +Date: Wed, 23 Jun 2010 19:45:05 -0400 +Subject: [PATCH] Apply new-windows-always-on-top to newly + raised/activated windows + +A window that raises itself or activates itself is in many ways +like a completely new window. (Once a window is out of the user's +site, they really have no idea if it's mapped or has been withdrawn +by the user.) + +If the user has set the new-windows-always-on-top key to make the +behavior for a focus-stealing-prevented *new* window "raise but not +focus", then they'll want the same behavior in the case of +windows that attempt to raise or activate themselves as well. + +https://bugzilla.gnome.org/show_bug.cgi?id=599261 +--- + src/core/window.c | 35 +++++++++++++++++++++++++++++--- + src/org.gnome.metacity.gschema.xml.in | 6 +++++ + 2 files changed, 37 insertions(+), 4 deletions(-) + +diff --git a/src/core/window.c b/src/core/window.c +index b6a69b0..897161e 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -2970,6 +2970,8 @@ window_activate (MetaWindow *window, + MetaWorkspace *workspace) + { + gboolean can_ignore_outdated_timestamps; ++ gboolean only_raise = FALSE; ++ + meta_topic (META_DEBUG_FOCUS, + "_NET_ACTIVE_WINDOW message sent for %s at time %u " + "by client type %u.\n", +@@ -2991,8 +2993,28 @@ window_activate (MetaWindow *window, + "last_user_time (%u) is more recent; ignoring " + " _NET_ACTIVE_WINDOW message.\n", + window->display->last_user_time); +- meta_window_set_demands_attention(window); +- return; ++ if (meta_prefs_get_new_windows_always_on_top () && ++ meta_prefs_get_raise_on_click ()) ++ { ++ /* The new_windows_only_on_top preference causes new ++ * focus-denied windows to get raised but not focused ++ * instead of set to demands attention. For consistency, we ++ * do the same here with windows that are "new to the user" ++ * - that self activate and are focus-stealing prevented. We ++ * can't just raise the window and return here because the ++ * window might be on a different workspace, so we need the ++ * handling below. The check for meta_prefs_get_raise_on_click () ++ * is because that preference, if off, somewhat unexpectedl ++ * akes windows not raise on self-activation. If that is changed ++ * than the test should be removed here. ++ */ ++ only_raise = TRUE; ++ } ++ else ++ { ++ meta_window_set_demands_attention (window); ++ return; ++ } + } + + /* For those stupid pagers, get a valid timestamp and show a warning */ +@@ -3041,7 +3063,8 @@ window_activate (MetaWindow *window, + meta_topic (META_DEBUG_FOCUS, + "Focusing window %s due to activation\n", + window->desc); +- meta_window_focus (window, timestamp); ++ if (!only_raise) ++ meta_window_focus (window, timestamp); + } + + /* This function exists since most of the functionality in window_activate +@@ -4759,11 +4782,15 @@ meta_window_configure_request (MetaWindow *window, + "broken behavior and the request is being ignored.\n", + window->desc); + } ++ /* the new_windows_always_on_top check is because a window that ++ * spontaneously restacks itself to the top is a lot like a new ++ * window that doesn't get focus */ + 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)) ++ active_window->net_wm_user_time) && ++ !meta_prefs_get_new_windows_always_on_top ()) + { + meta_topic (META_DEBUG_STACK, + "Ignoring xconfigure stacking request from %s (with " +diff --git a/src/org.gnome.metacity.gschema.xml.in b/src/org.gnome.metacity.gschema.xml.in +index d69d525..edc1b70 100644 +--- a/src/org.gnome.metacity.gschema.xml.in ++++ b/src/org.gnome.metacity.gschema.xml.in +@@ -66,6 +66,12 @@ + 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. ++ ++ This key also affects windows that try to activate or raise themselves ++ themselves but don't succeed in getting the the focus. Without ++ this key being set, such windows are flashed in the taskbar. With ++ this key set they, like entirely new windows, are raised but not ++ focused. + + + +-- +1.7.9 + diff --git a/SOURCES/Dont-focus-ancestor-window-on-a-different-workspac.patch b/SOURCES/Dont-focus-ancestor-window-on-a-different-workspac.patch new file mode 100644 index 0000000..4df7902 --- /dev/null +++ b/SOURCES/Dont-focus-ancestor-window-on-a-different-workspac.patch @@ -0,0 +1,40 @@ +From 0734ddbfaacff73b80747272ad7044ff904290f6 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 e877b19..6ffea30 100644 +--- a/src/core/workspace.c ++++ b/src/core/workspace.c +@@ -975,7 +975,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.7.9 + diff --git a/SOURCES/Exclude-the-current-application-from-no_focus_window.patch b/SOURCES/Exclude-the-current-application-from-no_focus_window.patch new file mode 100644 index 0000000..b2a4577 --- /dev/null +++ b/SOURCES/Exclude-the-current-application-from-no_focus_window.patch @@ -0,0 +1,69 @@ +From 3a8164d5ddf688db9cb00657861351febf013e72 Mon Sep 17 00:00:00 2001 +From: "Owen W. Taylor" +Date: Wed, 23 Jun 2010 16:49:37 -0400 +Subject: [PATCH] Exclude the current application from no-focus-windows + setting + +The idea of the no-focus-windows setting is to allow identifying +legacy application windows that are stealing focus from other +applications and suppress that behavior. Sometimes its not possible to +identify specific problem windows of an application and its +necessary to blanket add all windows of the application. In this +case no-focus-windows can disrupt the internal flow of focus +within the application. + +On the assumption that apps internally handle focus correctly +and have been tested not to steal focus from themselves at +annoying times, we exclude windows of the the current application +from no-focus-windows. + +https://bugzilla.gnome.org/show_bug.cgi?id=599248 +--- + src/core/window.c | 11 ++++++++++- + src/org.gnome.metacity.gschema.xml.in | 3 +++ + 2 files changed, 13 insertions(+), 1 deletions(-) + +diff --git a/src/core/window.c b/src/core/window.c +index 5440160..6f5c280 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -1980,12 +1980,21 @@ window_state_on_map (MetaWindow *window, + gboolean *places_on_top) + { + gboolean intervening_events; ++ MetaWindow *focus_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. ++ * ++ * This doesn't apply to applications taking focus from themselves; ++ * the assumption is applications have been properly tested to internally ++ * handle focus properly. + */ +- if (meta_prefs_window_is_no_focus (window->title, window->res_class)) ++ focus_window = window->display->focus_window; ++ if (focus_window && ++ !meta_window_same_application (window, focus_window) && ++ !meta_window_same_client (window, focus_window) && ++ meta_prefs_window_is_no_focus (window->title, window->res_class)) + intervening_events = TRUE; + else + intervening_events = intervening_user_event_occurred (window); +diff --git a/src/org.gnome.metacity.gschema.xml.in b/src/org.gnome.metacity.gschema.xml.in +index 6900fa6..e4f86bd 100644 +--- a/src/org.gnome.metacity.gschema.xml.in ++++ b/src/org.gnome.metacity.gschema.xml.in +@@ -41,6 +41,9 @@ + WM_CLASS matches the shell-style glob pattern <glob>. + (and <expr> <expr>) (or <expr> <expr>) (not <expr): Boolean combinations + of expressions. ++ ++ New windows from the current active application are unaffected by ++ this setting. + + + +-- +1.7.9 + diff --git a/SOURCES/For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch b/SOURCES/For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch new file mode 100644 index 0000000..6fbd49e --- /dev/null +++ b/SOURCES/For-mouse-and-sloppy-focus-return-to-mouse-mode-on.patch @@ -0,0 +1,396 @@ +From a24b336303c50e74f7d5e8582049dfae0d70329d 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 feee851..fee321c 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; + +@@ -501,4 +509,7 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display); + /* In above-tab-keycode.c */ + guint meta_display_get_above_tab_keycode (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 2e959b6..5bcf025 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); +@@ -1778,67 +1782,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 G_DESKTOP_FOCUS_MODE_SLOPPY: + case G_DESKTOP_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() == G_DESKTOP_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() == G_DESKTOP_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 G_DESKTOP_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; +@@ -5095,6 +5118,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 () == G_DESKTOP_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 G_DESKTOP_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 () != G_DESKTOP_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 08d861e..3c0ef95 100644 +--- a/src/core/keybindings.c ++++ b/src/core/keybindings.c +@@ -2082,7 +2082,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, +@@ -2686,7 +2686,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); + +@@ -2809,7 +2809,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, +@@ -2838,7 +2838,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 +@@ -3079,7 +3079,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.7.9 + diff --git a/SOURCES/Stop-confusing-GDK-s-grab-tracking.patch b/SOURCES/Stop-confusing-GDK-s-grab-tracking.patch new file mode 100644 index 0000000..c289453 --- /dev/null +++ b/SOURCES/Stop-confusing-GDK-s-grab-tracking.patch @@ -0,0 +1,200 @@ +From ab0428a82f8233829c36e2a3ac0ed0848571c59d Mon Sep 17 00:00:00 2001 +From: "Owen W. Taylor" +Date: Wed, 9 Jun 2010 19:38:35 -0400 +Subject: [PATCH] Stop confusing GDK's grab tracking + +With client side windows, mixing GDK event delivery with explicit calls +to XUngrabPointer() can result in GDK losing button release events +it expects to get. This means that GDK thinks there is an implicit +grab in effect when there is none and send events to the wrong window. + +Avoid this by bypassing GDK's event handling for most mouse events. +We do a simplified conversion of the X event into a GdkEvent and send +it to directly to libgtk for delivery. + +We make an exception when a GDK grab is already in effect - this is +needed for the correct operation of menus. + +http://bugzilla.gnome.org/show_bug.cgi?id=599181 +--- + src/core/display-private.h | 7 ++ + src/core/display.c | 131 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 138 insertions(+), 0 deletions(-) + +diff --git a/src/core/display-private.h b/src/core/display-private.h +index fee321c..7f779fd 100644 +--- a/src/core/display-private.h ++++ b/src/core/display-private.h +@@ -232,6 +232,13 @@ struct _MetaDisplay + /* Closing down the display */ + int closing; + ++ /* To detect double clicks */ ++ guint button_click_number; ++ Window button_click_window; ++ int button_click_x; ++ int button_click_y; ++ guint32 button_click_time; ++ + /* Managed by group.c */ + GHashTable *groups_by_leader; + +diff --git a/src/core/display.c b/src/core/display.c +index 5bcf025..0c5f61d 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -77,6 +77,7 @@ + #include + #endif + #include ++#include + + #define GRAB_OP_IS_WINDOW_SWITCH(g) \ + (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \ +@@ -1362,6 +1363,133 @@ meta_display_queue_autoraise_callback (MetaDisplay *display, + display->autoraise_window = window; + } + ++/* We do some of our event handling in core/frames.c, which expects ++ * GDK events delivered by GTK+. However, since the transition to ++ * client side windows, we can't let GDK see button events, since the ++ * client-side tracking of implicit and explicit grabs it does will ++ * get confused by our direct use of X grabs. ++ * ++ * So we do a very minimal GDK => GTK event conversion here and send on the ++ * events we care about, and then filter them out so they don't go ++ * through the normal GDK event handling. ++ * ++ * To reduce the amount of code, the only events fields filled out ++ * below are the ones that frames.c uses. If frames.c is modified to ++ * use more fields, more fields need to be filled out below. ++ */ ++ ++static gboolean ++maybe_send_event_to_gtk (MetaDisplay *display, ++ XEvent *xevent) ++{ ++ /* We're always using the default display */ ++ GdkDisplay *gdk_display = gdk_display_get_default (); ++ GdkEvent gdk_event; ++ GdkWindow *gdk_window; ++ Window window; ++ ++ switch (xevent->type) ++ { ++ case ButtonPress: ++ case ButtonRelease: ++ window = xevent->xbutton.window; ++ break; ++ case MotionNotify: ++ window = xevent->xmotion.window; ++ break; ++ case EnterNotify: ++ case LeaveNotify: ++ window = xevent->xcrossing.window; ++ break; ++ default: ++ return FALSE; ++ } ++ ++ gdk_window = gdk_window_lookup_for_display (gdk_display, window); ++ if (gdk_window == NULL) ++ return FALSE; ++ ++ /* If GDK already things it has a grab, we better let it see events; this ++ * is the menu-navigation case and events need to get sent to the appropriate ++ * (client-side) subwindow for individual menu items. ++ */ ++ if (gdk_display_pointer_is_grabbed (gdk_display)) ++ return FALSE; ++ ++ memset (&gdk_event, 0, sizeof (gdk_event)); ++ ++ switch (xevent->type) ++ { ++ case ButtonPress: ++ case ButtonRelease: ++ if (xevent->type == ButtonPress) ++ { ++ GtkSettings *settings = gtk_settings_get_default (); ++ int double_click_time; ++ int double_click_distance; ++ ++ g_object_get (settings, ++ "gtk-double-click-time", &double_click_time, ++ "gtk-double-click-distance", &double_click_distance, ++ NULL); ++ ++ if (xevent->xbutton.button == display->button_click_number && ++ xevent->xbutton.window == display->button_click_window && ++ xevent->xbutton.time < display->button_click_time + double_click_time && ++ ABS (xevent->xbutton.x - display->button_click_x) <= double_click_distance && ++ ABS (xevent->xbutton.y - display->button_click_y) <= double_click_distance) ++ { ++ gdk_event.button.type = GDK_2BUTTON_PRESS; ++ ++ display->button_click_number = 0; ++ } ++ else ++ { ++ gdk_event.button.type = GDK_BUTTON_PRESS; ++ display->button_click_number = xevent->xbutton.button; ++ display->button_click_window = xevent->xbutton.window; ++ display->button_click_time = xevent->xbutton.time; ++ display->button_click_x = xevent->xbutton.x; ++ display->button_click_y = xevent->xbutton.y; ++ } ++ } ++ else ++ { ++ gdk_event.button.type = GDK_BUTTON_RELEASE; ++ } ++ ++ gdk_event.button.window = gdk_window; ++ gdk_event.button.button = xevent->xbutton.button; ++ gdk_event.button.time = xevent->xbutton.time; ++ gdk_event.button.x = xevent->xbutton.x; ++ gdk_event.button.y = xevent->xbutton.y; ++ gdk_event.button.x_root = xevent->xbutton.x_root; ++ gdk_event.button.y_root = xevent->xbutton.y_root; ++ ++ break; ++ case MotionNotify: ++ gdk_event.motion.type = GDK_MOTION_NOTIFY; ++ gdk_event.motion.window = gdk_window; ++ break; ++ case EnterNotify: ++ case LeaveNotify: ++ gdk_event.crossing.type = xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY; ++ gdk_event.crossing.window = gdk_window; ++ gdk_event.crossing.x = xevent->xcrossing.x; ++ gdk_event.crossing.y = xevent->xcrossing.y; ++ break; ++ default: ++ g_assert_not_reached (); ++ break; ++ } ++ ++ /* If we've gotten here, we've filled in the gdk_event and should send it on */ ++ ++ gtk_main_do_event (&gdk_event); ++ ++ return TRUE; ++} ++ + /** + * This is the most important function in the whole program. It is the heart, + * it is the nexus, it is the Grand Central Station of Metacity's world. +@@ -2387,6 +2515,9 @@ event_callback (XEvent *event, + event, + window); + } ++ ++ if (maybe_send_event_to_gtk (display, event)) ++ filter_out_event = TRUE; + + display->current_time = CurrentTime; + return filter_out_event; +-- +1.7.9 + diff --git a/SOURCES/dnd-keynav.patch b/SOURCES/dnd-keynav.patch new file mode 100644 index 0000000..32f86cf --- /dev/null +++ b/SOURCES/dnd-keynav.patch @@ -0,0 +1,11 @@ +--- metacity-2.27.0/src/core/display.c 2009-06-07 21:35:13.623787399 -0400 ++++ hacked/src/core/display.c 2009-06-06 00:20:58.889278832 -0400 +@@ -3307,7 +3307,7 @@ + meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow, + timestamp); + +- if (!display->grab_have_pointer) ++ if (!display->grab_have_pointer && !grab_op_is_keyboard (op)) + { + meta_topic (META_DEBUG_WINDOW_OPS, + "XGrabPointer() failed\n"); diff --git a/SOURCES/fresh-tooltips.patch b/SOURCES/fresh-tooltips.patch new file mode 100644 index 0000000..aaa9ab7 --- /dev/null +++ b/SOURCES/fresh-tooltips.patch @@ -0,0 +1,287 @@ +diff -up metacity-2.30.2/src/ui/fixedtip.c.fresh-tooltips metacity-2.30.2/src/ui/fixedtip.c +--- metacity-2.30.2/src/ui/fixedtip.c.fresh-tooltips 2010-09-04 12:09:53.000000000 -0400 ++++ metacity-2.30.2/src/ui/fixedtip.c 2010-09-29 13:27:27.931194002 -0400 +@@ -50,23 +50,214 @@ static int screen_right_edge = 0; + */ + static int screen_bottom_edge = 0; + ++static void ++draw_round_rect (cairo_t *cr, ++ gdouble aspect, ++ gdouble x, ++ gdouble y, ++ gdouble corner_radius, ++ gdouble width, ++ gdouble height) ++{ ++ gdouble radius = corner_radius / aspect; ++ ++ cairo_move_to (cr, x + radius, y); ++ ++ /* top-right, left of the corner */ ++ cairo_line_to (cr, x + width - radius, y); ++ ++ /* top-right, below the corner */ ++ cairo_arc (cr, ++ x + width - radius, y + radius, radius, ++ -90.0f * G_PI / 180.0f, 0.0f * G_PI / 180.0f); ++ ++ /* bottom-right, above the corner */ ++ cairo_line_to (cr, x + width, y + height - radius); ++ ++ /* bottom-right, left of the corner */ ++ cairo_arc (cr, ++ x + width - radius, y + height - radius, radius, ++ 0.0f * G_PI / 180.0f, 90.0f * G_PI / 180.0f); ++ ++ /* bottom-left, right of the corner */ ++ cairo_line_to (cr, x + radius, y + height); ++ ++ /* bottom-left, above the corner */ ++ cairo_arc (cr, ++ x + radius, y + height - radius, radius, ++ 90.0f * G_PI / 180.0f, 180.0f * G_PI / 180.0f); ++ ++ /* top-left, below the corner */ ++ cairo_line_to (cr, x, y + radius); ++ ++ /* top-left, right of the corner */ ++ cairo_arc (cr, ++ x + radius, y + radius, radius, ++ 180.0f * G_PI / 180.0f, 270.0f * G_PI / 180.0f); ++ ++ cairo_close_path (cr); ++} ++ ++ ++static void ++fill_background (GtkWidget *widget, ++ cairo_t *cr) ++{ ++ GdkColor color; ++ gdouble r, g, b; ++ gint radius; ++ gdouble background_alpha; ++ ++ if (gdk_screen_is_composited (gtk_widget_get_screen (widget))) ++ background_alpha = 0.90; ++ else ++ background_alpha = 1.0; ++ ++ radius = MIN (widget->style->xthickness, widget->style->ythickness); ++ radius = MAX (radius, 1); ++ ++ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); ++ cairo_paint (cr); ++ cairo_set_operator (cr, CAIRO_OPERATOR_OVER); ++ ++ draw_round_rect (cr, ++ 1.0, 0.5, 0.5, radius, ++ widget->allocation.width - 1, ++ widget->allocation.height - 1); ++ ++ color = widget->style->bg [GTK_STATE_NORMAL]; ++ r = (float)color.red / 65535.0; ++ g = (float)color.green / 65535.0; ++ b = (float)color.blue / 65535.0; ++ cairo_set_source_rgba (cr, r, g, b, background_alpha); ++ cairo_fill_preserve (cr); ++ ++ color = widget->style->bg [GTK_STATE_SELECTED]; ++ r = (float) color.red / 65535.0; ++ g = (float) color.green / 65535.0; ++ b = (float) color.blue / 65535.0; ++ ++ cairo_set_source_rgba (cr, r, g, b, background_alpha); ++ cairo_set_line_width (cr, 1.0); ++ cairo_stroke (cr); ++} ++ ++static void ++update_shape (GtkWidget *window) ++{ ++ GdkBitmap *mask; ++ cairo_t *cr; ++ gint width, height; ++ gint radius; ++ gboolean new_style; ++ ++ gtk_widget_style_get (window, "new-tooltip-style", &new_style, NULL); ++ ++ if (!new_style) ++ { ++ gtk_widget_shape_combine_mask (window, NULL, 0, 0); ++ return; ++ } ++ ++ gtk_window_get_size (GTK_WINDOW (window), &width, &height); ++ ++ if (gdk_screen_is_composited (gtk_widget_get_screen (window))) ++ { ++ gtk_widget_shape_combine_mask (window, NULL, 0, 0); ++ return; ++ } ++ ++ radius = MIN (window->style->xthickness, window->style->ythickness); ++ radius = MAX (radius, 1); ++ ++ mask = (GdkBitmap *) gdk_pixmap_new (NULL, width, height, 1); ++ cr = gdk_cairo_create (mask); ++ if (cairo_status (cr) == CAIRO_STATUS_SUCCESS) ++ { ++ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); ++ cairo_paint (cr); ++ ++ cairo_set_operator (cr, CAIRO_OPERATOR_OVER); ++ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); ++ draw_round_rect (cr, 1.0, 0, 0, radius + 1, width, height); ++ cairo_fill (cr); ++ ++ gtk_widget_shape_combine_mask (window, mask, 0, 0); ++ } ++ cairo_destroy (cr); ++ ++ g_object_unref (mask); ++} ++ + static gint +-expose_handler (GtkTooltip *tooltips) ++expose_handler (GtkWidget *window) + { +- gtk_paint_flat_box (gtk_widget_get_style (tip), gtk_widget_get_window (tip), +- GTK_STATE_NORMAL, GTK_SHADOW_OUT, +- NULL, tip, "tooltip", +- 0, 0, -1, -1); ++ cairo_t *context; ++ cairo_surface_t *surface; ++ cairo_t *cr; ++ gboolean new_style; ++ ++ gtk_widget_style_get (window, "new-tooltip-style", &new_style, NULL); ++ ++ if (new_style) ++ { ++ context = gdk_cairo_create (window->window); ++ ++ cairo_set_operator (context, CAIRO_OPERATOR_SOURCE); ++ surface = cairo_surface_create_similar (cairo_get_target (context), ++ CAIRO_CONTENT_COLOR_ALPHA, ++ window->allocation.width, ++ window->allocation.height); ++ cr = cairo_create (surface); ++ ++ fill_background (window, cr); ++ ++ cairo_destroy (cr); ++ cairo_set_source_surface (context, surface, 0, 0); ++ cairo_paint (context); ++ cairo_surface_destroy (surface); ++ cairo_destroy (context); ++ ++ update_shape (window); ++ } ++ else ++ { ++ gtk_paint_flat_box (window->style, ++ window->window, ++ GTK_STATE_NORMAL, ++ GTK_SHADOW_OUT, ++ NULL, ++ window, ++ "tooltip", ++ 0, 0, ++ window->allocation.width, ++ window->allocation.height); ++ } + + return FALSE; + } + ++static void ++on_style_set (GtkWidget *widget, GtkStyle *prev) ++{ ++ GtkWidget *alignment; ++ ++ alignment = gtk_bin_get_child (GTK_BIN (widget)); ++ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), ++ widget->style->ythickness, ++ widget->style->ythickness, ++ widget->style->xthickness, ++ widget->style->xthickness); ++ gtk_widget_queue_draw (widget); ++} ++ + void + meta_fixed_tip_show (Display *xdisplay, int screen_number, + int root_x, int root_y, + const char *markup_text) + { + int w, h; ++ GtkWidget *alignment; + + if (tip == NULL) + { +@@ -77,6 +268,7 @@ meta_fixed_tip_show (Display *xdisplay, + GdkScreen *gdk_screen; + GdkRectangle monitor; + gint mon_num; ++ GdkColormap *rgba; + + gdk_screen = gdk_display_get_screen (gdk_display_get_default (), + screen_number); +@@ -86,25 +278,47 @@ meta_fixed_tip_show (Display *xdisplay, + gdk_screen_get_monitor_geometry (gdk_screen, mon_num, &monitor); + screen_right_edge = monitor.x + monitor.width; + screen_bottom_edge = monitor.y + monitor.height; ++ ++ rgba = gdk_screen_get_rgba_colormap (gdk_screen); ++ if (rgba) ++ gtk_widget_set_colormap (tip, rgba); ++ ++#if 0 ++ g_signal_connect (tip, "composited-changed", ++ G_CALLBACK (on_composited_changed), NULL); ++ g_signal_connect (tip, "realize", ++ G_CALLBACK (on_realized), NULL); ++#endif + } +- ++ + gtk_widget_set_app_paintable (tip, TRUE); + gtk_window_set_resizable (GTK_WINDOW (tip), FALSE); +- gtk_widget_set_name (tip, "gtk-tooltips"); +- gtk_container_set_border_width (GTK_CONTAINER (tip), 4); ++ gtk_widget_set_name (tip, "gtk-tooltip"); ++ gtk_widget_realize (tip); + +- g_signal_connect_swapped (tip, "expose_event", +- G_CALLBACK (expose_handler), NULL); ++ g_signal_connect (tip, "expose_event", ++ G_CALLBACK (expose_handler), NULL); ++ ++ alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); ++ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), ++ tip->style->ythickness, ++ tip->style->ythickness, ++ tip->style->xthickness, ++ tip->style->xthickness); ++ gtk_widget_show (alignment); ++ gtk_container_add (GTK_CONTAINER (tip), alignment); + + label = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); +- gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_widget_show (label); +- +- gtk_container_add (GTK_CONTAINER (tip), label); ++ ++ gtk_container_add (GTK_CONTAINER (alignment), label); + + g_signal_connect (tip, "destroy", + G_CALLBACK (gtk_widget_destroyed), &tip); ++ ++ g_signal_connect (tip, "style-set", ++ G_CALLBACK (on_style_set), NULL); + } + + gtk_label_set_markup (GTK_LABEL (label), markup_text); diff --git a/SOURCES/metacity-2.28-empty-keybindings.patch b/SOURCES/metacity-2.28-empty-keybindings.patch new file mode 100644 index 0000000..b2ae51b --- /dev/null +++ b/SOURCES/metacity-2.28-empty-keybindings.patch @@ -0,0 +1,40 @@ +From 857ac4b0682dec32ba55e4080fa7ec560a2481a0 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 78aa353..ef9fcfc 100644 +--- a/src/ui/ui.c ++++ b/src/ui/ui.c +@@ -954,7 +954,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); +@@ -1041,7 +1041,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.7.9 + diff --git a/SOURCES/metacity-2.28-xioerror-unknown-display.patch b/SOURCES/metacity-2.28-xioerror-unknown-display.patch new file mode 100644 index 0000000..5de5f8d --- /dev/null +++ b/SOURCES/metacity-2.28-xioerror-unknown-display.patch @@ -0,0 +1,58 @@ +From 04f775d77d53bca92faee883258d787b89255ef8 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.7.9 + diff --git a/SOURCES/stop-spamming-xsession-errors.patch b/SOURCES/stop-spamming-xsession-errors.patch new file mode 100644 index 0000000..864cf6e --- /dev/null +++ b/SOURCES/stop-spamming-xsession-errors.patch @@ -0,0 +1,16 @@ +diff -up metacity-2.25.8/src/core/display.c.stop-spamming-xsession-errors metacity-2.25.8/src/core/display.c +--- metacity-2.25.8/src/core/display.c.stop-spamming-xsession-errors 2008-11-23 00:28:37.000000000 -0500 ++++ metacity-2.25.8/src/core/display.c 2008-11-24 21:40:33.000000000 -0500 +@@ -3264,10 +3264,12 @@ meta_display_begin_grab_op (MetaDisplay + + if (display->grab_op != META_GRAB_OP_NONE) + { ++#if 0 + if (window) + meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect\n", + op, window->desc, display->grab_op, + display->grab_window ? display->grab_window->desc : "none"); ++#endif + return FALSE; + } + diff --git a/SPECS/metacity.spec b/SPECS/metacity.spec new file mode 100644 index 0000000..f77f41c --- /dev/null +++ b/SPECS/metacity.spec @@ -0,0 +1,1039 @@ +Summary: Unobtrusive window manager +Name: metacity +Version: 2.34.13 +Release: 7%{?dist} +URL: http://download.gnome.org/sources/metacity/ +Source0: http://download.gnome.org/sources/metacity/2.34/metacity-%{version}.tar.xz +# http://bugzilla.gnome.org/show_bug.cgi?id=558723 +Patch4: stop-spamming-xsession-errors.patch +# http://bugzilla.gnome.org/show_bug.cgi?id=135056 +Patch5: dnd-keynav.patch + +# fedora specific patches +Patch12: fresh-tooltips.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=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 +Patch119: Exclude-the-current-application-from-no_focus_window.patch +# https://bugzilla.gnome.org/show_bug.cgi?id=599261 +Patch20: Add-a-newwindowsalwaysontop-preference.patch +Patch120: Apply-new_windows_always_on_top-to-newly-raised-acti.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 +# https://bugzilla.gnome.org/show_bug.cgi?id=599181 +Patch28: Stop-confusing-GDK-s-grab-tracking.patch +# https://bugzilla.gnome.org/show_bug.cgi?id=622517 +Patch29: Allow-breaking-out-from-maximization-during-mouse.patch + +Patch40: 0001-doc-Update-man-pages.patch + +License: GPLv2+ +Group: User Interface/Desktops +BuildRequires: gtk2-devel +BuildRequires: pango-devel +BuildRequires: fontconfig-devel +BuildRequires: gsettings-desktop-schemas-devel +BuildRequires: desktop-file-utils +BuildRequires: libglade2-devel +BuildRequires: autoconf, automake, libtool, gnome-common +BuildRequires: intltool +BuildRequires: startup-notification-devel +BuildRequires: libtool automake autoconf gettext +BuildRequires: xorg-x11-proto-devel +BuildRequires: libSM-devel, libICE-devel, libX11-devel +BuildRequires: libXext-devel, libXinerama-devel, libXrandr-devel, libXrender-devel +BuildRequires: libXcursor-devel +BuildRequires: libXcomposite-devel, libXdamage-devel +# for gnome-keybindings.pc +BuildRequires: control-center +BuildRequires: yelp-tools +BuildRequires: zenity +BuildRequires: dbus-devel +BuildRequires: libcanberra-devel +BuildRequires: itstool + +Requires: startup-notification +Requires: gsettings-desktop-schemas +# for /usr/share/control-center/keybindings, /usr/share/gnome/wm-properties +Requires: control-center-filesystem +Requires: zenity + +# http://bugzilla.redhat.com/605675 +Provides: firstboot(windowmanager) = metacity + +%description +Metacity is a window manager that integrates nicely with the GNOME desktop. +It strives to be quiet, small, stable, get on with its job, and stay out of +your attention. + +%package devel +Group: Development/Libraries +Summary: Development files for metacity +Requires: %{name} = %{version}-%{release} + +%description devel +This package contains the files needed for compiling programs using +the metacity-private library. Note that you are not supposed to write +programs using the metacity-private library, since it is a private +API. This package exists purely for technical reasons. + +%prep +%setup -q +%patch4 -p1 -b .stop-spamming-xsession-errors +%patch5 -p1 -b .dnd-keynav +%patch12 -p1 -b .fresh-tooltips + +%patch16 -p1 -b .focus-different-workspace +%patch18 -p1 -b .focus-on-motion +%patch19 -p1 -b .no-focus-windows +%patch119 -p1 -b .no-focus-windows-current-app +%patch20 -p1 -b .always-on-top +%patch120 -p1 -b .always-on-top-activate +%patch24 -p1 -b .empty-keybindings +%patch25 -p1 -b .xioerror-unknown-display +%patch28 -p1 -b .grab-tracking +%patch29 -p1 -b .mouse-unmaximize +%patch40 -p1 -b .man-page + +# force regeneration +rm -f src/org.gnome.metacity.gschema.valid + +%build +CPPFLAGS="$CPPFLAGS -I$RPM_BUILD_ROOT%{_includedir}" +export CPPFLAGS + +# Always rerun configure for now +rm -f configure +(if ! test -x configure; then autoreconf -i -f; fi; + %configure --disable-static --disable-schemas-compile) + +SHOULD_HAVE_DEFINED="HAVE_SM HAVE_XINERAMA HAVE_XFREE_XINERAMA HAVE_SHAPE HAVE_RANDR HAVE_STARTUP_NOTIFICATION" + +for I in $SHOULD_HAVE_DEFINED; do + if ! grep -q "define $I" config.h; then + echo "$I was not defined in config.h" + grep "$I" config.h + exit 1 + else + echo "$I was defined as it should have been" + grep "$I" config.h + fi +done + +make CPPFLAGS="$CPPFLAGS" LIBS="$LIBS" %{?_smp_mflags} + +%install +make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" + +find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' + +# the desktop file is not valid, I've complained on metacity-devel-list +#desktop-file-install --vendor "" --delete-original \ +# --dir $RPM_BUILD_ROOT%{_datadir}/applications \ +# $RPM_BUILD_ROOT%{_datadir}/applications/metacity.desktop + +%find_lang %{name} --all-name --with-gnome + +%post -p /sbin/ldconfig + +%posttrans +glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : + +%postun +/sbin/ldconfig +if [ $1 -eq 0 ]; then + glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : +fi + +%files -f %{name}.lang +%doc README AUTHORS COPYING NEWS HACKING doc/theme-format.txt doc/metacity-theme.dtd rationales.txt +%{_bindir}/metacity +%{_bindir}/metacity-message +%{_datadir}/glib-2.0/schemas/* +%{_datadir}/GConf/gsettings/metacity-schemas.convert +%{_datadir}/metacity +%{_datadir}/themes/* +%{_datadir}/gnome-control-center/keybindings/* +%{_libdir}/lib*.so.* +%{_mandir}/man1/metacity.1.gz +%{_mandir}/man1/metacity-message.1.gz +%{_datadir}/applications/metacity.desktop +%{_datadir}/gnome/wm-properties/metacity-wm.desktop + +%files devel +%defattr(-,root,root,-) +%{_bindir}/metacity-theme-viewer +%{_bindir}/metacity-window-demo +%{_includedir}/* +%{_libdir}/lib*.so +%{_libdir}/pkgconfig/* +%{_mandir}/man1/metacity-theme-viewer.1.gz +%{_mandir}/man1/metacity-window-demo.1.gz + +%changelog +* Fri Jan 24 2014 Daniel Mach - 2.34.13-7 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 2.34.13-6 +- Mass rebuild 2013-12-27 + +* Thu May 16 2013 Florian Müllner - 2.34.13-5 +- Include documentation update from upstream + +* Thu Feb 14 2013 Fedora Release Engineering - 2.34.13-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Thu Nov 22 2012 Florian Müllner - 2.34.13-3 +- Clean up leftovers from upstream patch removed in commit 24481514 + +* Tue Nov 20 2012 Matthias Clasen - 2.34.13-2 +- Don't use a patch fuzz of 999 + +* Mon Oct 15 2012 Florian Müllner - 2.34.13-1 +- Update to 2.34.13 + +* Tue Sep 04 2012 Richard Hughes - 2.34.8-1 +- Update to 2.34.8 +- Add yelp-tools BR + +* Mon Aug 06 2012 Florian Müllner - 2.34.5-1 +- Update to new upstream version, drop upstreamed patch + +* Fri Jul 20 2012 Fedora Release Engineering - 2.34.3-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed Jul 11 2012 Ville Skyttä - 2.34.3-3 +- Fix %%post scriptlet dependencies. + +* Thu Jun 14 2012 Peter Robinson - 2.34.3-2 +- Add options to disable mouse button modifers + +* Tue Mar 20 2012 Florian Müllner - 2.34.3-1 +- Update to new upstream version + +* Sat Feb 18 2012 Michael Schwendt - 2.34.2-3 +- Execute %%postun via /bin/sh not /sbin/ldconfig. + +* Wed Feb 15 2012 Florian Müllner 2.34.2-2 +- Explicitly require gsettings-desktop-schemas + +* Thu Feb 09 2012 Florian Müllner 2.34.2-1 +- Update to 2.34.2 +- Remove patches: + - screenshot-forkbomb.patch: screenshot keybindings have been moved + to gnome-settings-daemon + - workspace.patch: default preference values now defined in + gsettings-desktop-schemas + - default-window-icon.patch: included upstream +- Rebase remaining patches +- Adjust spec file to dropped GConf dependency + +* Fri Jan 13 2012 Fedora Release Engineering - 2.34.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Thu Nov 10 2011 Adam Jackson 2.34.1-2 +- Rebuild to break bogus libpng dep + +* Wed Jul 6 2011 Matthias Clasen - 2.34.1-1 +- Update to 2.34.1 + +* Sun May 22 2011 Daniel Drake - 2.34.0-2 +- Add upstream patch to allow keybindings ungrab, needed for Sugar + +* Mon Apr 4 2011 Matthias Clasen - 2.34.0-1 +- Update to 2.34.0 + +* Mon Feb 28 2011 Colin Walters - 2.32.0-1.git20110228 +- Upstream git snapshot + Includes Alt-` binding which we really want for gnome-shell +- Drop upstreamed patches +- Switch to my auto-autogen snippet which automatically invokes configure, + so we can build from a pure git archive +- Instead of using autoreconf, just rm -f configure and let autogen do + the work +- BR gnome-common so autogen works + +* Tue Feb 08 2011 Fedora Release Engineering - 2.30.3-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Thu Jan 13 2011 Matthias Clasen - 2.30.3-4 +- Drop gnome-themes dependency + +* Tue Oct 26 2010 Parag Nemade - 2.30.3-3 +- Gconf2 scriptlet accepts schema file names without file extension. + +* Mon Oct 18 2010 Parag Nemade - 2.30.3-2 +- Merge-review cleanup (#226138) + +* Thu Sep 30 2010 Matthias Clasen - 2.30.3-1 +- Update to 2.30.3 + +* Wed Sep 29 2010 Matthias Clasen - 2.30.2-1 +- Update to 2.30.2 + +* Wed Sep 15 2010 Rex Dieter - 2.30.0-8 +- firstboot -> metacity dep (#605675) + +* Tue Jul 20 2010 Dan Horák - 2.30.0-7 +- updated the nofocuswindows_prefs patch for gcc 4.5 + +* Wed Jun 23 2010 Owen Taylor - 2.30.0-6 +- Add patch to allow breaking out from maximization during mouse resize + (gnome bz 622517) + +* Wed Jun 9 2010 Owen Taylor - 2.30.0-5 +- Add a patch to fix confusion between windows (rhbz #533066) +- Add additional tweeks no_focus_windows and new_windows_always_on_top + preferences (gnome bz 599248, gnome bz 599261) + +* Tue Apr 20 2010 Matthias Clasen - 2.30.0-3 +- Include the default window icon + +* Mon Apr 5 2010 Matthias Clasen - 2.30.0-2 +- Don't crash on titlebar right-click + +* Wed Mar 31 2010 Matthias Clasen - 2.30.0-1 +- Update to 2.30.0 + +* Fri Feb 26 2010 Matthias Clasen - 2.28.1-3 +- Fix linking with pedantic linkers + +* Wed Jan 27 2010 Owen Taylor - 2.28.1-2 +- Update to 2.28.1, remove 7 patches now applied upstream + +* Sun Jan 3 2010 Owen Taylor - 2.28.0-15 +- Fix crash in _IceTransClose (rhbz 551994) + The previous patch for rhbz 539905 didn't actually fix the + problem; the ICE connection was still being closed twice. + +* Thu Dec 17 2009 Owen Taylor - 2.28.0-14 +- Fix crash in in tooltip on_style_set() (rhbz 546509) +- Fix Crash in SmcSetProperties() on exit (rhbz 539905, gnome 604867) + +* Thu Dec 10 2009 Owen Taylor - 2.28.0-13 +- 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 473224) + 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 - Handle XError and XIOError for unknown displays (rhbz 537845) + +* Thu Nov 26 2009 Matthias Clasen - 2.28.0-11 +- Fix a problem with the previous change + +* Tue Nov 24 2009 Matthias Clasen - 2.28.0-10 +- Disable key repeat for screenshot keybinding (#506369) + +* Thu Nov 05 2009 Ray Strode 2.28.0-9 +- One stab at the metacity patch + +* Thu Nov 05 2009 Ray Strode 2.28.0-8 +- Minor clean ups to last patch based on feedback from + Owen + +* Thu Nov 05 2009 Ray Strode 2.28.0-7 +- Don't do bad things on sigterm + +* Wed Oct 28 2009 Matthias Clasen - 2.28.0-6 +- Make tooltips look sharper + +* Wed Oct 21 2009 Matthias Clasen - 2.28.0-4 +- Make tooltips look match GTK+ + +* Thu Oct 15 2009 Matthias Clasen - 2.28.0-3 +- Tweak the default number of workspaces + +* Tue Sep 22 2009 Matthias Clasen - 2.28.0-1 +- Update to 2.28.0 + +* Tue Sep 8 2009 Matthias Clasen - 2.27.1-1 +- Update to 2.27.1 + +* Wed Sep 2 2009 Peter Robinson - 2.27.0-9 +- Add upstreamed patch for option to force fullscreen for sugar +- https://bugzilla.redhat.com/show_bug.cgi?id=516225 + +* Fri Aug 28 2009 Lennart Poettering - 2.27.0-8 +- Actually apply the patch from -7 + +* Fri Aug 28 2009 Lennart Poettering - 2.27.0-7 +- Apply another trivial patch related to sound events +- http://bugzilla.gnome.org/show_bug.cgi?id=593358 + +* Fri Aug 28 2009 Lennart Poettering - 2.27.0-6 +- Apply two trivial patches for bell/sound +- http://bugzilla.gnome.org/show_bug.cgi?id=593356 +- http://bugzilla.gnome.org/show_bug.cgi?id=593355 + +* Sat Aug 22 2009 Owen Taylor - 2.27.0-5 +- Add a fix for http://bugzilla.gnome.org/show_bug.cgi?id=588119, + remove no-longer-needed no-lame-dialog patch + +* Wed Aug 5 2009 Matthias Clasen - 2.27.0-4 +- Change the default theme to Clearlooks + +* Sat Jul 25 2009 Fedora Release Engineering - 2.27.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Sun Jun 7 2009 Matthias Clasen - 2.27.0-2 +- Make DND work better +- Don't show a lame dialog + +* Sun May 31 2009 Matthias Clasen - 2.27.0-1 +- Update to 2.27.0 + +* Mon Apr 27 2009 Matthias Clasen - 2.26.0-2 +- Don't drop schemas translations from po files + +* Mon Mar 16 2009 Matthias Clasen - 2.26.0-1 +- Update to 2.26.0 + +* Wed Mar 11 2009 Matthias Clasen - 2.25.144-6 +- Fix interaction with autohide panels + +* Wed Feb 25 2009 Fedora Release Engineering - 2.25.144-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Sat Feb 21 2009 Matthias Clasen - 2.25.144-4 +- Don't force the bell (#486137) + +* Wed Feb 18 2009 Matthias Clasen - 2.25.144-3 +- Update the theme patch to apply to the right file + +* Tue Feb 10 2009 Matthias Clasen - 2.25.144-2 +- Use libcanberra to play the alert sound from the sound theme + for the audible system bell + +* Tue Feb 3 2009 Matthias Clasen - 2.25.144-1 +- Update to 2.25.144 + +* Mon Jan 5 2009 Matthias Clasen - 2.25.89-1 +- Update to 2.25.89 + +* Tue Dec 16 2008 Matthias Clasen - 2.25.55-1 +- Update to 2.25.55 + +* Mon Dec 15 2008 Matthias Clasen - 2.25.34-3 +- Clean _NET_SUPPORTING_WM_CHECK on shutdown +- Fix BuildRequires + +* Wed Dec 3 2008 Matthias Clasen - 2.25.34-1 +- Update to 2.25.34 + +* Mon Nov 24 2008 Matthias Clasen - 2.25.8-4 +- Update to 2.25.8 + +* Sat Nov 22 2008 Matthias Clasen - 2.25.5-4 +- Tweak %%summary and %%description +- Fix BuildRequires + +* Wed Nov 12 2008 Matthias Clasen - 2.25.5-1 +- Update to 2.25.5 + +* Fri Oct 31 2008 Soren Sandmann - 2.24.0-3 +- Don't spam .xsession-errors so hard (bug 467802) + +* Thu Sep 25 2008 Matthias Clasen - 2.24.0-2 +- Save some space + +* Mon Sep 22 2008 Matthias Clasen - 2.24.0-1 +- Update to 2.24.0 + +* Fri Sep 19 2008 Matthias Clasen - 2.23.610-2 +- Fix some memory leaks + +* Tue Sep 9 2008 Matthias Clasen - 2.23.610-1 +- Update to 2.23.610 + +* Tue Sep 2 2008 Matthias Clasen - 2.23.233-1 +- Update to 2.23.233 + +* Fri Aug 22 2008 Matthias Clasen - 2.23.144-1 +- Update to 2.23.144 + +* Tue Jul 15 2008 Matthias Clasen - 2.23.55-1 +- Update to 2.23.55 + +* Tue Jun 17 2008 Matthias Clasen - 2.23.34-1 +- Update to 2.23.34 + +* Tue May 27 2008 Matthias Clasen - 2.23.21-1 +- Update to 2.23.21 + +* Mon May 5 2008 Matthias Clasen - 2.23.13-1 +- Update to 2.23.13 + +* Thu Apr 24 2008 Matthias Clasen - 2.23.8-1 +- Update to 2.23.8 +- Drop obsolete patches + +* Thu Apr 24 2008 Matthias Clasen - 2.22.0-3 +- Fix a possible crash in the appearance capplet with + invalid metacity themes (launchpad #199402) + +* Wed Mar 12 2008 Marco Pesenti Gritti - 2.22.0-2 +- Add patch to fix focus of keep-above windows + http://bugzilla.gnome.org/show_bug.cgi?id=519188 + +* Mon Mar 10 2008 Matthias Clasen - 2.22.0-1 +- Update to 2.22.0 + +* Wed Feb 27 2008 Matthias Clasen - 2.21.21-1 +- Update to 2.21.21 + +* Tue Feb 12 2008 Matthias Clasen - 2.21.13-1 +- Update to 2.21.13 + +* Wed Feb 6 2008 Colin Walters - 2.21.8.svn3554-1 +- Drop random macros at top of file; spec files should be as amenable + to static analysis as possible, easing our way into the bright future + where our software build process isn't a horrible mismash of a + preprocessor on shell script, with manual editing required, + but something scriptable. +- Update to SVN 3554, to which our patches were designed to apply +- Readd patch metacity-2.21.13-dont-move-windows.patch, which makes + Firefox behave as those multiple-workspace users desire. + +* Wed Feb 6 2008 Matthias Clasen - 2.21.8-1 +- Update to 2.21.8 + +* Sun Feb 3 2008 Matthias Clasen - 2.21.5-3 +- Make skip-taskbar windows appear in the ctrl-alt-tab list + +* Thu Dec 20 2007 Colin Walters - 2.21.5-2 +- Add patch for avoiding moving windows across workspaces + This makes clicking on links in firefox do what you want. + http://bugzilla.gnome.org/show_bug.cgi?id=482354 + +* Wed Dec 19 2007 Matthias Clasen - 2.21.5-1 +- Update to 2.21.5, including the new compositor + +* Sun Dec 16 2007 Matthias Clasen - 2.21.3-1 +- Update to 2.21.3 + +* Sun Nov 18 2007 Matthias Clasen - 2.21.2-1 +- Update to 2.21.2 + +* Tue Nov 13 2007 Matthias Clasen - 2.21.1-1 +- Update to 2.21.1 + +* Sun Nov 11 2007 Matthias Clasen - 2.20.0-4 +- Fix a crash when the number of workspaces is 1 + +* Thu Oct 18 2007 Colin Walters - 2.20.0-3 +- Add patch to fix workspace behavior when presenting normal windows + +* Thu Sep 27 2007 Ray Strode - 2.20.0-2 +- Drop dep on redhat-artwork, add one on nodoka + +* Sun Sep 16 2007 Matthias Clasen - 2.20.0-1 +- Update to 2.20.0 + +* Tue Sep 11 2007 Ray Strode - 2.19.55-4 +- fix crash on logout (and on the subsequent login, bug 243761) + +* Tue Aug 21 2007 Adam Jackson - 2.19.55-3 +- Rebuild for build id + +* Sun Aug 12 2007 Matthias Clasen - 2.19.55-2 +- Switch default theme to Nodoka + +* Tue Aug 7 2007 Matthias Clasen - 2.19.55-1 +- Update to 2.19.55 + +* Tue Aug 7 2007 Matthias Clasen - 2.19.34-3 +- Update license field + +* Wed Jul 25 2007 Jesse Keating - 2.19.34-2 +- Rebuild for RH #249435 + +* Mon Jul 23 2007 Matthias Clasen - 2.19.34-1 +- Update to 2.19.34 + +* Fri Jul 6 2007 Matthias Clasen - 2.19.21-3 +- Require control-center-filesystem + +* Thu Jul 5 2007 Matthias Clasen - 2.19.21-2 +- Fix keybindings + +* Mon Jun 18 2007 Matthias Clasen - 2.19.21-1 +- Update to 2.19.21 + +* Sun Jun 17 2007 Matthias Clasen - 2.19.13-2 +- Clean up directory ownership + +* Fri Jun 15 2007 Matthias Clasen - 2.19.13-1 +- Update to 2.19.13 + +* Mon Jun 11 2007 Matthias Clasen - 2.19.8-2 +- Don't ship .so.0 in the -devel package (#243689) + +* Mon Jun 4 2007 Matthias Clasen - 2.19.8-1 +- Update to 2.19.8 + +* Sat May 19 2007 Matthias Clasen - 2.19.5-1 +- Update to 2.19.5 + +* Tue Apr 3 2007 Matthias Clasen - 2.18.0-2 +- Split off a devel package (#203547) +- Some spec file cleanups (#21573) + +* Tue Mar 13 2007 Matthias Clasen - 2.18.0-1 +- Update to 2.18.0 + +* Wed Feb 28 2007 Matthias Clasen - 2.17.8-1 +- Update to 2.17.8 + +* Thu Feb 22 2007 Matthias Clasen - 2.17.5-2 +- Fix a spec file typo +- Don't ship static libraries + +* Wed Jan 17 2007 Matthias Clasen - 2.17.5-1 +- Update to 2.17.5 + +* Mon Nov 6 2006 Matthias Clasen - 2.17.2-1 +- Update to 2.17.2 + +* Fri Oct 20 2006 Matthias Clasen - 2.17.1-1 +- Update to 2.17.1 + +* Wed Oct 18 2006 Matthias Clasen - 2.16.0-7 +- Fix scripts according to packaging guidelines + +* Tue Oct 17 2006 Matthias Clasen - 2.16.0-6 +- Add missing Requires (#203813) + +* Sun Oct 01 2006 Jesse Keating - 2.16.0-5 +- rebuilt for unwind info generation, broken in gcc-4.1.1-21 + +* Mon Sep 25 2006 Soren Sandmann - 2.16.0-4.fc6 +- Build + +* Fri Sep 21 2006 Soren Sandmann +- Remove GL dependencies. +- Remove static-cm patch +- add patch to fix more CurrentTime race conditions (bug 206263) + +* Thu Sep 14 2006 Ray Strode - 2.16.0-3.fc6 +- remove stale ctrl-alt-delete patch + +* Sat Sep 9 2006 Soren Sandmann - 2.16.0-2.fc6 +- Add patch from Elijah that may fix bug 204519 + +* Mon Sep 4 2006 Matthias Clasen - 2.16.0-1.fc6 +- Update to 2.16.0 + +* Mon Aug 21 2006 Matthias Clasen - 2.15.34-1.fc6 +- Update to 2.15.34 +- Require pkgconfig, since we installing a .pc file + +* Sun Aug 13 2006 Matthias Clasen - 2.15.21-1.fc6 +- Update to 2.15.21 +- Uninstall gconf schemas in %%preun + +* Mon Aug 7 2006 Soren Sandmann - 2.15.13-2 +- Remove leftover snapshot string. + +* Mon Aug 7 2006 Soren Sandmann - 2.15.13-1 +- Update to 2.15.13. Disable compositing manager. + +* Wed Jul 12 2006 Jesse Keating - 2.15.5-6.1 +- rebuild + +* Tue Jun 13 2006 Michael J. Knox - 2.15.5-6 +- remove BR on automake14, use current automake instead + +* Tue Jun 6 2006 Soren Sandmann 2.15.5-5 +- Update to new tarball with different intltool magic in it. + +* Tue Jun 6 2006 Soren Sandmann 2.15.5-4 +- Update intltool BuildRequires to 0.35 + +* Fri Jun 2 2006 Soren Sandmann 2.15.5-2 +- Update intltool BuildRequires to 0.34.90 + +* Thu Jun 1 2006 Soren Sandmann 2.15.5-1 +- Update metacity to a cvs snapshot, and libcm 0.0.22. (The standalone + libcm package is being put through the package review process). + +* Tue May 30 2006 Kristian Høgsberg 2.15.3-4 +- Bump for rawhide build. + +* Mon May 29 2006 Kristian Høgsberg - 2.15.3-3 +- Bump libGL build requires so libcm picks up the right tfp tokens. + +* Thu May 18 2006 Soren Sandmann 2.15.3-2 +- Update libcm to 0.0.21 + +* Wed May 17 2006 Matthias Clasen 2.15.3-1 +- Update to 2.15.3 + +* Fri May 12 2006 Adam Jackson 2.15.2-2 +- Update protocol dep to 7.0-13 for final EXT_tfp enums, and rebuild. + +* Thu May 11 2006 Soren Sandmann 2.15.2-1 +- Update to metacity 2.15.2 + +* Tue Apr 18 2006 Kristian Høgsberg 2.15.0-6 +- Bump for fc5-bling build. + +* Thu Apr 13 2006 Soren Sandmann 2.15.0-5 +- Update to libcm 0.0.19 + +* Wed Apr 12 2006 Kristian Høgsberg 2.15.0-4 +- Bump for fc5-bling rebuild. + +* Thu Apr 6 2006 Soren Sandmann - 2.16.0-3 +- Bump libcm to 0.0.18. + +* Mon Apr 3 2006 Soren Sandmann - 2.15.0-2 +- Fix leftover libcm-snapshot-date, buildrequire libXcomposite-devel >= 0.3 + +* Fri Mar 31 2006 Soren Sandmann - 2.15.0 +- Update to 2.15.0 + +* Mon Mar 13 2006 Ray Strode - 2.14.0-1 +- update to 2.14.0 + +* Mon Mar 6 2006 Ray Strode - 2.13.144-1 +- update to 2.13.144 +- add bling patch from HEAD + +* Sun Feb 19 2006 Ray Strode - 2.13.89.0.2006.02.17-2 +- disable compositor on s390 s390x and ppc64 + +* Fri Feb 17 2006 Ray Strode - 2.13.89.0.2006.02.17-1 +- Update to latest cvs snapshot to give meaningful failure error + messages +- Don't remove build root in install, because it triggers a + rebuild of metacity + +* Thu Feb 16 2006 Ray Strode - 2.13.89.0.2006.02.16-1 +- Update to cvs snapshot to add the ability to + runtime enable compositor +- change %%makeinstall to make install DESTDIR=.. + +* Mon Feb 13 2006 Matthias Clasen - 2.13.89-1 +- Update to 2.13.89 + +* Fri Feb 10 2006 Jesse Keating - 2.13.55-1.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 2.13.55-1.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Mon Jan 30 2006 Matthias Clasen 2.13.55-1 +- Update to 2.13.55 + +* Thu Jan 26 2006 Matthias Clasen 2.13.34-1 +- Update to 2.13.34 + +* Mon Jan 16 2006 Ray Strode 2.13.21-1 +- Update to 2.13.21 + +* Fri Jan 13 2006 Matthias Clasen 2.13.13-1 +- Update to 2.13.13 + +* Tue Jan 03 2006 Matthias Clasen 2.13.8-1 +- Update to 2.13.8 + +* Thu Dec 15 2005 Matthias Clasen 2.13.5-1 +- Update to 2.13.5 + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Thu Dec 1 2005 Matthias Clasen 2.13.3-1 +- Update to 2.13.3 + +* Mon Nov 21 2005 Ray Strode 2.13.2-1 +- Update to 2.13.2 + +* Fri Nov 18 2005 Bill Nottingham +- remove references to obsolete X11R6 paths + +* Thu Oct 6 2005 Matthias Clasen 2.12.1-1 +- Update to 2.12.1 + +* Thu Sep 8 2005 Matthias Clasen 2.12.0-1 +- Update to 2.12.0 + +* Thu Sep 1 2005 Ray Strode 2.11.2-3 +- truncate long window titles to 512 characters (bug 164071) + +* Tue Aug 16 2005 Warren Togami 2.11.2-2 +- rebuild for new cairo + +* Tue Aug 9 2005 Ray Strode 2.11.2-1 +- Update to 2.11.2 (fixes bug 163745) + +* Fri Aug 5 2005 Matthias Clasen 2.11.1-1 +- New upstream version + +* Mon Jul 18 2005 Matthias Clasen 2.11.0-3 +- fix xcursor detection + +* Wed Jul 13 2005 Matthias Clasen 2.11.0-1 +- newer upstream version + +* Mon May 30 2005 Warren Togami 2.10.0-2 +- raise demands attention (#157271 newren) + +* Sun Apr 3 2005 Ray Strode 2.10.0-1 +- Update to 2.10.0 + +* Thu Mar 17 2005 Matthias Clasen 2.9.21-2 +- Switch to Clearlooks as default theme + +* Mon Feb 28 2005 Matthias Clasen 2.9.21-1 +- Update to 2.9.21 + +* Wed Feb 9 2005 Matthias Clasen 2.9.13-1 +- Update to 2.9.13 + +* Fri Jan 28 2005 Matthias Clasen 2.9.8-1 +- Update to 2.9.8 + +* Sat Oct 16 2004 Havoc Pennington 2.8.6-2 +- remove all the rerunning of autotools, intltool, etc. cruft; seemed to be breaking build + +* Fri Oct 15 2004 Havoc Pennington 2.8.6-1 +- upgrade to 2.8.6, fixes a lot of focus bugs primarily. + +* Fri Oct 15 2004 Soren Sandmann - 2.8.5-3 +- Kludge around right alt problem (#132379) + +* Mon Oct 11 2004 Alexander Larsson - 2.8.5-2 +- Require startup-notification 0.7 (without this we'll crash) + +* Thu Sep 23 2004 Alexander Larsson - 2.8.5-1 +- update to 2.8.5 + +* Tue Aug 31 2004 Alex Larsson 2.8.4-1 +- update to 2.8.4 + +* Tue Aug 24 2004 Warren Togami 2.8.3-1 +- update to 2.8.3 + +* Thu Aug 5 2004 Mark McLoughlin 2.8.2-1 +- Update to 2.8.2 +- Remove systemfont patch - upstream now + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Thu May 6 2004 Havoc Pennington 2.8.1-2 +- fix mangled Summary + +* Thu May 6 2004 Havoc Pennington 2.8.1-1 +- 2.8.1 + +* Thu Apr 1 2004 Alex Larsson 2.8.0-1 +- update to 2.8.0 + +* Wed Mar 10 2004 Mark McLoughlin 2.7.1-1 +- Update to 2.7.1 + +* Tue Mar 02 2004 Elliot Lee +- rebuilt + +* Wed Feb 25 2004 Alexander Larsson 2.7.0-1 +- update to 2.7.0 +- removed reduced resouces patch (its now upstream) + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Mon Oct 27 2003 Havoc Pennington 2.6.3-1 +- 2.6.3 + +* Wed Oct 1 2003 Havoc Pennington 2.6.2-1 +- 2.6.2 + +* Thu Sep 4 2003 Havoc Pennington 2.5.3-3 +- put reduced resources patch back in + +* Fri Aug 22 2003 Elliot Lee 2.5.3-2 +- Work around libXrandr need for extra $LIBS + +* Fri Aug 15 2003 Alexander Larsson 2.5.3-1 +- update for gnome 2.3 + +* Mon Jul 28 2003 Havoc Pennington 2.4.55-7 +- rebuild + +* Mon Jul 28 2003 Havoc Pennington 2.4.55-6 +- backport the "reduced_resources" patch with wireframe + +* Mon Jul 07 2003 Christopher Blizzard 2.4.55-4 +- add patch to fix mouse down problems in mozilla + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Thu May 29 2003 Havoc Pennington 2.4.55-2 +- rebuild + +* Thu May 29 2003 Havoc Pennington 2.4.55-1 +- 2.4.55 + +* Wed May 14 2003 Florian La Roche +- add proper ldconfig calls for shared libs + +* Mon Feb 24 2003 Elliot Lee +- rebuilt + +* Fri Feb 21 2003 Havoc Pennington 2.4.34-2 +- fix a crash in multihead situations, #84412 + +* Wed Feb 5 2003 Havoc Pennington 2.4.34-1 +- 2.4.34 +- try disabling smp_mflags and see if it fixes build + +* Wed Jan 22 2003 Havoc Pennington +- 2.4.21.90 with a bunch o' fixes + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Thu Jan 16 2003 Havoc Pennington +- bind Ctrl+Alt+Del to logout, #72973 + +* Wed Jan 15 2003 Havoc Pennington +- 2.4.13.90 cvs snap with event queue lag fix + +* Fri Jan 10 2003 Havoc Pennington +- 2.4.13 + +* Thu Dec 12 2002 Havoc Pennington +- 2.4.8 + +* Mon Dec 2 2002 Havoc Pennington +- 2.4.5.90 +- add little script after configure that checks what config.h + contains, to be sure we detected all the right features. + +* Tue Oct 29 2002 Havoc Pennington +- 2.4.3 +- remove patches that have gone upstream + +* Tue Aug 27 2002 Havoc Pennington +- fix shaded window decorations in Bluecurve theme + +* Sat Aug 24 2002 Havoc Pennington +- fix the mplayer-disappears-on-de-fullscreen bug + +* Sat Aug 24 2002 Havoc Pennington +- add some fixes from CVS for #71163 #72379 #72478 #72513 + +* Thu Aug 22 2002 Havoc Pennington +- patch .schemas.in instead of .schemas so we get right default theme/fonts + +* Tue Aug 20 2002 Havoc Pennington +- grow size of top resize, and display proper cursor on enter notify +- require latest intltool to try and fix metacity.schemas by + regenerating it in non-UTF-8 locale + +* Thu Aug 15 2002 Havoc Pennington +- default to Sans Bold font, fixes #70920 and matches graphic design spec + +* Thu Aug 15 2002 Havoc Pennington +- 2.4.0.91 with raise/lower keybindings for msf, fixes to fullscreen +- more apps that probably intend to be, fix for changing number of + workspaces, fix for moving windows in multihead + +* Tue Aug 13 2002 Havoc Pennington +- update build requires + +* Mon Aug 12 2002 Havoc Pennington +- upgrade to cvs snap 2.4.0.90 with pile of bugfixes from + this weekend +- change default theme to bluecurve and require new redhat-artwork + +* Tue Aug 6 2002 Havoc Pennington +- 2.4.0 +- themes are moved, require appropriate redhat-artwork + +* Thu Aug 1 2002 Havoc Pennington +- munge the desktop file to be in toplevel menus and + not show in KDE + +* Tue Jul 23 2002 Havoc Pennington +- don't use system font by default as metacity's + font is now in the system font dialog + +* Tue Jul 23 2002 Havoc Pennington +- 2.3.987.92 cvs snap + +* Fri Jul 12 2002 Havoc Pennington +- 2.3.987.91 cvs snap + +* Mon Jun 24 2002 Havoc Pennington +- 2.3.987.90 cvs snap + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Sun Jun 16 2002 Havoc Pennington +- rebuild for new libraries + +* Mon Jun 10 2002 Havoc Pennington +- rebuild in different environment + +* Mon Jun 10 2002 Havoc Pennington +- 2.3.987 +- default to redhat theme + +* Fri Jun 07 2002 Havoc Pennington +- rebuild in different environment + +* Tue Jun 4 2002 Havoc Pennington +- 2.3.610.90 cvs snap + +* Sun May 26 2002 Tim Powers +- automated rebuild + +* Mon May 20 2002 Havoc Pennington +- rebuild in different environment + +* Fri May 17 2002 Havoc Pennington +- 2.3.377 + +* Thu May 2 2002 Havoc Pennington +- 2.3.233 + +* Thu Apr 25 2002 Havoc Pennington +- rebuild in different environment +- add gconf schemas boilerplate + +* Mon Apr 15 2002 Havoc Pennington +- 2.3.89 + +* Tue Oct 30 2001 Havoc Pennington +- 2.3.34 + +* Fri Oct 13 2001 Havoc Pennington +- 2.3.21 + +* Mon Sep 17 2001 Havoc Pennington +- 2.3.8 +- 2.3.13 + +* Wed Sep 5 2001 Havoc Pennington +- Initial build. + +