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