summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Udaltsov <svu@gnome.org>2009-08-29 01:02:25 +0000
committerSergey Udaltsov <svu@gnome.org>2009-08-29 01:02:25 +0000
commitb682c9636d2dc7cbf41b31a7b05119a22c875839 (patch)
tree1304264bdb00b777be6dd477d7914dbc8bfb0a55
parent82e87a4c9d351162875b3392169e7c7971bfe390 (diff)
downloadlibxklavier-b682c9636d2dc7cbf41b31a7b05119a22c875839.tar.gz
fixing race condition - focus_in arriving when last focused window is gone
-rw-r--r--ChangeLog6
-rw-r--r--libxklavier/xklavier_evt.c71
2 files changed, 50 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 85d0207..85aa4f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-08-29 svu
+
+ * libxklavier/xklavier_evt.c: sometimes focus_in arrives when the
+ previously focused window is already destroyed. That causes BadMatch
+ and all kinds of trouble. The code should handle that case correctly.
+
2009-08-17 svu
* libxklavier/xklavier_xkb.c: fixed a bug with XIE check,
diff --git a/libxklavier/xklavier_evt.c b/libxklavier/xklavier_evt.c
index 918a5f8..eb1601a 100644
--- a/libxklavier/xklavier_evt.c
+++ b/libxklavier/xklavier_evt.c
@@ -100,6 +100,8 @@ xkl_engine_process_focus_in_evt(XklEngine * engine,
XFocusChangeEvent * fev)
{
Window win;
+ Window prev_toplevel_win =
+ xkl_engine_priv(engine, curr_toplvl_win);
Window toplevel_win;
XklState selected_window_state;
@@ -135,36 +137,51 @@ xkl_engine_process_focus_in_evt(XklEngine * engine,
if (xkl_engine_get_toplevel_window_state
(engine, toplevel_win, &selected_window_state)) {
- if (xkl_engine_priv(engine, curr_toplvl_win) !=
- toplevel_win) {
- gboolean old_win_transparent, new_win_transparent;
- XklState tmp_state;
-
- old_win_transparent =
- xkl_engine_is_toplevel_window_transparent
- (engine,
- xkl_engine_priv(engine, curr_toplvl_win));
- if (old_win_transparent)
- xkl_debug(150,
- "Leaving transparent window\n");
+ if (prev_toplevel_win != toplevel_win) {
+ gboolean new_win_transparent;
+ Window parent = (Window) NULL, root =
+ (Window) NULL, *children = NULL;
+ guint nchildren = 0;
/*
- * Reload the current state from the current window.
- * Do not do it for transparent window - we keep the state from
- * the _previous_ window.
+ * If previous focused window exists - handle transparency and state
+ * (optional)
*/
- if (!old_win_transparent &&
- xkl_engine_get_toplevel_window_state(engine,
- xkl_engine_priv
- (engine,
- curr_toplvl_win),
- &tmp_state))
- {
- xkl_engine_update_current_state(engine,
- tmp_state.group,
- tmp_state.indicators,
- "Loading current (previous) state from the current (previous) window");
- }
+ if (xkl_engine_query_tree
+ (engine, prev_toplevel_win, &root, &parent,
+ &children, &nchildren) == Success) {
+ XklState tmp_state;
+ gboolean old_win_transparent =
+ xkl_engine_is_toplevel_window_transparent
+ (engine, prev_toplevel_win);
+
+ if (children != NULL)
+ XFree(children);
+
+ if (old_win_transparent)
+ xkl_debug(150,
+ "Leaving transparent window\n");
+ /*
+ * Reload the current state from the current window.
+ * Do not do it for transparent window - we keep the state from
+ * the _previous_ window.
+ */
+ if (!old_win_transparent
+ &&
+ xkl_engine_get_toplevel_window_state
+ (engine, prev_toplevel_win,
+ &tmp_state)) {
+ xkl_engine_update_current_state
+ (engine, tmp_state.group,
+ tmp_state.indicators,
+ "Loading current (previous) state from the current (previous) window");
+ }
+ } else
+ xkl_debug(150,
+ "Current (previous) window "
+ WINID_FORMAT
+ " does not exist any more, so transparency/state are not analyzed\n",
+ prev_toplevel_win);
xkl_engine_priv(engine, curr_toplvl_win) =
toplevel_win;