Skip to content

Instantly share code, notes, and snippets.

@richardgv
Created September 18, 2013 02:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save richardgv/6603796 to your computer and use it in GitHub Desktop.
Save richardgv/6603796 to your computer and use it in GitHub Desktop.
chjj/compton #99: Possible focus detection fix
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