focus.c for the Openbox window manager
Copyright (c) 2006 Mikael Magnusson
- Copyright (c) 2003 Ben Jansens
+ Copyright (c) 2003-2007 Dana Jansens
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
static void focus_cycle_destructor(ObClient *client, gpointer data)
{
- /* end cycling if the target disappears */
+ /* end cycling if the target disappears. CurrentTime is fine, time won't
+ be used
+ */
if (focus_cycle_target == client)
- focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+ focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, CurrentTime);
}
static Window createWindow(Window parent, gulong mask,
XSync(ob_display, FALSE);
}
- /* in the middle of cycling..? kill it. */
+ /* in the middle of cycling..? kill it. CurrentTime is fine, time won't
+ be used.
+ */
if (focus_cycle_target)
- focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+ focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, CurrentTime);
old = focus_client;
focus_client = client;
for (it = c->transients; it; it = g_slist_next(it)) {
if (it->data == top) return NULL;
ret = find_transient_recursive(it->data, top, skip);
- if (ret && ret != skip && client_normal(ret)) return ret;
- if (it->data != skip && client_normal(it->data)) return it->data;
+ if (ret && ret != skip && client_normal(ret) &&
+ client_can_focus(ret) && client_validate(ret))
+ return ret;
+ if (it->data != skip && client_normal(it->data) &&
+ client_can_focus(it->data) && client_validate(it->data))
+ return it->data;
}
return NULL;
}
return NULL;
}
-ObClient* focus_fallback_target(ObFocusFallbackType type)
+ObClient* focus_fallback_target(gboolean allow_refocus, ObClient *old)
{
GList *it;
- ObClient *old = NULL;
ObClient *target = NULL;
- old = focus_client;
-
- if ((type == OB_FOCUS_FALLBACK_UNFOCUSING
- || type == OB_FOCUS_FALLBACK_CLOSED) && old) {
- if (old->transient_for) {
- gboolean trans = FALSE;
-
- if (!config_focus_follow || config_focus_last)
- trans = TRUE;
- else {
- if ((target = client_under_pointer()) &&
- client_search_transient
- (client_search_top_transient(target), old))
+ if (!allow_refocus && old && old->transient_for) {
+ gboolean trans = FALSE;
+
+ if (!config_focus_follow || config_focus_last)
+ trans = TRUE;
+ else if ((target = client_under_pointer()) &&
+ client_search_transient
+ (client_search_top_parent(target), old))
+ trans = TRUE;
+
+ /* try for transient relations */
+ if (trans) {
+ if (old->transient_for == OB_TRAN_GROUP) {
+ for (it = focus_order[screen_desktop]; it;
+ it = g_list_next(it))
{
- trans = TRUE;
- }
- }
+ GSList *sit;
- /* try for transient relations */
- if (trans) {
- if (old->transient_for == OB_TRAN_GROUP) {
- for (it = focus_order[screen_desktop]; it;
- it = g_list_next(it))
+ for (sit = old->group->members; sit;
+ sit = g_slist_next(sit))
{
- GSList *sit;
-
- for (sit = old->group->members; sit;
- sit = g_slist_next(sit))
- {
- if (sit->data == it->data)
- if ((target =
- focus_fallback_transient(sit->data, old)))
- return target;
- }
+ if (sit->data == it->data)
+ if ((target =
+ focus_fallback_transient(sit->data, old)))
+ {
+ ob_debug("found in transient #1\n");
+ return target;
+ }
}
- } else {
- if ((target =
- focus_fallback_transient(old->transient_for, old)))
- return target;
+ }
+ } else {
+ if ((target =
+ focus_fallback_transient(old->transient_for, old)))
+ {
+ ob_debug("found in transient #2\n");
+ return target;
}
}
}
}
- if (config_focus_follow &&
- (type == OB_FOCUS_FALLBACK_UNFOCUSING || !config_focus_last))
+ ob_debug("trying pointer stuff\n");
+ if (config_focus_follow && !config_focus_last)
{
if ((target = client_under_pointer()))
- if (client_normal(target) && client_can_focus(target))
- return target;
+ if (allow_refocus || target != old)
+ if (client_normal(target) && client_can_focus(target) &&
+ client_validate(target)) {
+ ob_debug("found in pointer stuff\n");
+ return target;
+ }
}
#if 0
}
#endif
+ ob_debug("trying the focus order\n");
for (it = focus_order[screen_desktop]; it; it = g_list_next(it))
- if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old)
- if (client_normal(it->data) && client_can_focus(it->data))
+ if (allow_refocus || it->data != old)
+ if (client_normal(it->data) && client_can_focus(it->data) &&
+ client_validate(it->data))
+ {
+ ob_debug("found in focus order\n");
return it->data;
+ }
/* XXX fallback to the "desktop window" if one exists ?
could store it while going through all the windows in the loop right
return NULL;
}
-void focus_fallback(ObFocusFallbackType type)
+void focus_fallback(gboolean allow_refocus)
{
ObClient *new;
+ ObClient *old;
+
+ /* save this before moving focus away to nothing */
+ old = focus_client;
/* unfocus any focused clients.. they can be focused by Pointer events
and such, and then when I try focus them, I won't get a FocusIn event
*/
focus_set_client(NULL);
- if ((new = focus_fallback_target(type)))
+ if ((new = focus_fallback_target(allow_refocus, old)))
client_focus(new);
}
ft->type == OB_CLIENT_TYPE_MENU ||
ft->type == OB_CLIENT_TYPE_UTILITY))) &&
((ft->can_focus || ft->focus_notify) &&
- !ft->skip_taskbar &&
+ !ft->skip_pager &&
(ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)) &&
ft == client_focus_target(ft))
return TRUE;
}
void focus_cycle(gboolean forward, gboolean linear, gboolean interactive,
- gboolean dialog, gboolean done, gboolean cancel)
+ gboolean dialog, gboolean done, gboolean cancel, Time time)
{
static ObClient *first = NULL;
static ObClient *t = NULL;
done_cycle:
if (done && focus_cycle_target)
- client_activate(focus_cycle_target, FALSE, TRUE);
+ client_activate(focus_cycle_target, FALSE, TRUE, time);
t = NULL;
first = NULL;
}
void focus_directional_cycle(ObDirection dir, gboolean interactive,
- gboolean dialog, gboolean done, gboolean cancel)
+ gboolean dialog, gboolean done, gboolean cancel,
+ Time time)
{
static ObClient *first = NULL;
ObClient *ft = NULL;
done_cycle:
if (done && focus_cycle_target)
- client_activate(focus_cycle_target, FALSE, TRUE);
+ client_activate(focus_cycle_target, FALSE, TRUE, time);
first = NULL;
focus_cycle_target = NULL;