Created
September 18, 2013 02:44
-
-
Save richardgv/6603796 to your computer and use it in GitHub Desktop.
chjj/compton #99: Possible focus detection fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/c2.c b/src/c2.c | |
index e89638b..de221c0 100644 | |
--- a/src/c2.c | |
+++ b/src/c2.c | |
@@ -1055,7 +1055,7 @@ c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf, | |
case C2_L_PFULLSCREEN: tgt = win_is_fullscreen(ps, w); break; | |
case C2_L_POVREDIR: tgt = w->a.override_redirect; break; | |
case C2_L_PARGB: tgt = (WMODE_ARGB == w->mode); break; | |
- case C2_L_PFOCUSED: tgt = w->focused_real; break; | |
+ case C2_L_PFOCUSED: tgt = win_is_focused_real(ps, w); break; | |
case C2_L_PWMWIN: tgt = w->wmwin; break; | |
case C2_L_PCLIENT: tgt = w->client_win; break; | |
case C2_L_PLEADER: tgt = w->leader; break; | |
diff --git a/src/common.h b/src/common.h | |
index ea95235..ca1ef48 100644 | |
--- a/src/common.h | |
+++ b/src/common.h | |
@@ -954,8 +954,6 @@ typedef struct _win { | |
bool focused; | |
/// Override value of window focus state. Set by D-Bus method calls. | |
switch_t focused_force; | |
- /// Whether the window is actually focused. | |
- bool focused_real; | |
// Blacklist related members | |
/// Name of the window. | |
@@ -1705,12 +1703,15 @@ find_focused(session_t *ps) { | |
if (!ps->o.track_focus) | |
return NULL; | |
- for (win *w = ps->list; w; w = w->next) { | |
- if (w->focused_real && !w->destroyed) | |
- return w; | |
- } | |
+ return ps->active_win; | |
+} | |
- return NULL; | |
+/** | |
+ * Check if a window is really focused. | |
+ */ | |
+static inline bool | |
+win_is_focused_real(session_t *ps, const win *w) { | |
+ return ps->active_win == w; | |
} | |
/** | |
diff --git a/src/compton.c b/src/compton.c | |
index 55e638f..ad3edc0 100644 | |
--- a/src/compton.c | |
+++ b/src/compton.c | |
@@ -2066,7 +2066,7 @@ map_win(session_t *ps, Window id) { | |
|| IsViewable == w->a.map_state) | |
return; | |
- assert(!w->focused_real); | |
+ assert(!win_is_focused_real(ps, w)); | |
w->a.map_state = IsViewable; | |
@@ -2296,7 +2296,7 @@ calc_opacity(session_t *ps, win *w) { | |
} | |
// Respect active_opacity only when the window is physically focused | |
- if (OPAQUE == opacity && ps->o.active_opacity && w->focused_real) | |
+ if (OPAQUE == opacity && ps->o.active_opacity && win_is_focused_real(ps, w)) | |
opacity = ps->o.active_opacity; | |
} | |
@@ -2752,7 +2752,6 @@ add_win(session_t *ps, Window id, Window prev) { | |
.focused = false, | |
.focused_force = UNSET, | |
- .focused_real = false, | |
.name = NULL, | |
.class_instance = NULL, | |
@@ -3270,7 +3269,7 @@ win_update_focused(session_t *ps, win *w) { | |
w->focused = w->focused_force; | |
} | |
else { | |
- w->focused = w->focused_real; | |
+ w->focused = win_is_focused_real(ps, w); | |
// Use wintype_focus, and treat WM windows and override-redirected | |
// windows specially | |
@@ -3302,51 +3301,57 @@ win_set_focused(session_t *ps, win *w, bool focused) { | |
if (IsUnmapped == w->a.map_state) | |
return; | |
- if (w->focused_real != focused) { | |
- w->focused_real = focused; | |
+ if (win_is_focused_real(ps, w) == focused) return; | |
- // If window grouping detection is enabled | |
- if (ps->o.track_leader) { | |
- Window leader = win_get_leader(ps, w); | |
+ if (focused) | |
+ ps->active_win = w; | |
+ else if (w == ps->active_win) | |
+ ps->active_win = NULL; | |
- // If the window gets focused, replace the old active_leader | |
- if (w->focused_real && leader != ps->active_leader) { | |
- Window active_leader_old = ps->active_leader; | |
+ assert(win_is_focused_real(ps, w) == focused); | |
- ps->active_leader = leader; | |
+ // If window grouping detection is enabled | |
+ if (ps->o.track_leader) { | |
+ Window leader = win_get_leader(ps, w); | |
- group_update_focused(ps, active_leader_old); | |
- group_update_focused(ps, leader); | |
- } | |
- // If the group get unfocused, remove it from active_leader | |
- else if (!w->focused_real && leader && leader == ps->active_leader | |
- && !group_is_focused(ps, leader)) { | |
- ps->active_leader = None; | |
- group_update_focused(ps, leader); | |
- } | |
+ // If the window gets focused, replace the old active_leader | |
+ if (win_is_focused_real(ps, w) && leader != ps->active_leader) { | |
+ Window active_leader_old = ps->active_leader; | |
- // The window itself must be updated anyway | |
- win_update_focused(ps, w); | |
+ ps->active_leader = leader; | |
+ | |
+ group_update_focused(ps, active_leader_old); | |
+ group_update_focused(ps, leader); | |
} | |
- // Otherwise, only update the window itself | |
- else { | |
- win_update_focused(ps, w); | |
+ // If the group get unfocused, remove it from active_leader | |
+ else if (!win_is_focused_real(ps, w) && leader && leader == ps->active_leader | |
+ && !group_is_focused(ps, leader)) { | |
+ ps->active_leader = None; | |
+ group_update_focused(ps, leader); | |
} | |
- // Update everything related to conditions | |
- win_on_factor_change(ps, w); | |
+ // The window itself must be updated anyway | |
+ win_update_focused(ps, w); | |
+ } | |
+ // Otherwise, only update the window itself | |
+ else { | |
+ win_update_focused(ps, w); | |
+ } | |
+ | |
+ // Update everything related to conditions | |
+ win_on_factor_change(ps, w); | |
#ifdef CONFIG_DBUS | |
- // Send D-Bus signal | |
- if (ps->o.dbus) { | |
- if (w->focused_real) | |
- cdbus_ev_win_focusin(ps, w); | |
- else | |
- cdbus_ev_win_focusout(ps, w); | |
- } | |
-#endif | |
+ // Send D-Bus signal | |
+ if (ps->o.dbus) { | |
+ if (win_is_focused_real(ps, w)) | |
+ cdbus_ev_win_focusin(ps, w); | |
+ else | |
+ cdbus_ev_win_focusout(ps, w); | |
} | |
+#endif | |
} | |
+ | |
/** | |
* Update leader of a window. | |
*/ | |
@@ -3386,7 +3391,7 @@ win_set_leader(session_t *ps, win *w, Window nleader) { | |
// Update the old and new window group and active_leader if the window | |
// could affect their state. | |
Window cache_leader = win_get_leader(ps, w); | |
- if (w->focused_real && cache_leader_old != cache_leader) { | |
+ if (win_is_focused_real(ps, w) && cache_leader_old != cache_leader) { | |
ps->active_leader = cache_leader; | |
group_update_focused(ps, cache_leader_old); | |
@@ -3808,11 +3813,10 @@ ev_focus_report(XFocusChangeEvent* ev) { | |
*/ | |
inline static bool | |
ev_focus_accept(XFocusChangeEvent *ev) { | |
- return ev->detail == NotifyNonlinear | |
- || ev->detail == NotifyNonlinearVirtual; | |
+ return NotifyNormal == ev->mode || NotifyUngrab == ev->mode; | |
} | |
-inline static void | |
+static inline void | |
ev_focus_in(session_t *ps, XFocusChangeEvent *ev) { | |
#ifdef DEBUG_EVENTS | |
ev_focus_report(ev); | |
@@ -3821,12 +3825,9 @@ ev_focus_in(session_t *ps, XFocusChangeEvent *ev) { | |
if (!ev_focus_accept(ev)) | |
return; | |
- win *w = find_win(ps, ev->window); | |
- | |
- // To deal with events sent from windows just destroyed | |
- if (!w) return; | |
- | |
- win_set_focused(ps, w, true); | |
+ win *w = find_win_all(ps, ev->window); | |
+ if (w) | |
+ win_set_focused(ps, w, true); | |
} | |
inline static void | |
@@ -3838,12 +3839,9 @@ ev_focus_out(session_t *ps, XFocusChangeEvent *ev) { | |
if (!ev_focus_accept(ev)) | |
return; | |
- win *w = find_win(ps, ev->window); | |
- | |
- // To deal with events sent from windows just destroyed | |
- if (!w) return; | |
- | |
- win_set_focused(ps, w, false); | |
+ win *w = find_win_all(ps, ev->window); | |
+ if (w) | |
+ win_set_focused(ps, w, false); | |
} | |
inline static void | |
diff --git a/src/compton.h b/src/compton.h | |
index 1180ce3..8e41d62 100644 | |
--- a/src/compton.h | |
+++ b/src/compton.h | |
@@ -563,6 +563,19 @@ clear_cache_win_leaders(session_t *ps) { | |
static win * | |
find_toplevel2(session_t *ps, Window wid); | |
+/** | |
+ * Find matched window. | |
+ */ | |
+static inline win * | |
+find_win_all(session_t *ps, const Window wid) { | |
+ if (!wid || wid == ps->root || wid == ps->overlay) return NULL; | |
+ | |
+ win *w = find_win(ps, wid); | |
+ if (!w) w = find_toplevel(ps, wid); | |
+ if (!w) w = find_toplevel2(ps, wid); | |
+ return w; | |
+} | |
+ | |
static Window | |
win_get_leader_raw(session_t *ps, win *w, int recursions); | |
@@ -589,7 +602,7 @@ group_is_focused(session_t *ps, Window leader) { | |
for (win *w = ps->list; w; w = w->next) { | |
if (win_get_leader(ps, w) == leader && !w->destroyed | |
- && w->focused_real) | |
+ && win_is_focused_real(ps, w)) | |
return true; | |
} | |
diff --git a/src/dbus.c b/src/dbus.c | |
index 299c5ac..1d20a06 100644 | |
--- a/src/dbus.c | |
+++ b/src/dbus.c | |
@@ -722,7 +722,11 @@ cdbus_process_win_get(session_t *ps, DBusMessage *msg) { | |
cdbus_m_win_get_do(window_type, cdbus_reply_enum); | |
cdbus_m_win_get_do(wmwin, cdbus_reply_bool); | |
cdbus_m_win_get_do(leader, cdbus_reply_wid); | |
- cdbus_m_win_get_do(focused_real, cdbus_reply_bool); | |
+ // focused_real | |
+ if (!strcmp("focused_real", target)) { | |
+ cdbus_reply_bool(ps, msg, win_is_focused_real(ps, w)); | |
+ return true; | |
+ } | |
cdbus_m_win_get_do(fade_force, cdbus_reply_enum); | |
cdbus_m_win_get_do(shadow_force, cdbus_reply_enum); | |
cdbus_m_win_get_do(focused_force, cdbus_reply_enum); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment