#include "group.h"
#include "focus_cycle.h"
#include "screen.h"
-#include "prop.h"
#include "keyboard.h"
#include "focus.h"
#include "stacking.h"
+#include "obt/prop.h"
#include <X11/Xlib.h>
#include <glib.h>
if (reconfig) return;
/* reset focus to root */
- XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime);
+ XSetInputFocus(obt_display, PointerRoot, RevertToNone, CurrentTime);
}
static void push_to_top(ObClient *client)
Window active;
ob_debug_type(OB_DEBUG_FOCUS,
- "focus_set_client 0x%lx\n", client ? client->window : 0);
+ "focus_set_client 0x%lx", client ? client->window : 0);
if (focus_client == client)
return;
push_to_top(client);
/* remove hiliting from the window when it gets focused */
client_hilite(client, FALSE);
+
+ /* make sure the focus cycle popup shows things in the right order */
+ focus_cycle_reorder();
}
/* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
if (ob_state() != OB_STATE_EXITING) {
active = client ? client->window : None;
- PROP_SET32(RootWindow(ob_display, ob_screen),
- net_active_window, window, active);
+ OBT_PROP_SET32(obt_root(ob_screen), NET_ACTIVE_WINDOW, WINDOW, active);
}
}
GList *it;
ObClient *c;
- ob_debug_type(OB_DEBUG_FOCUS, "trying pointer stuff\n");
+ ob_debug_type(OB_DEBUG_FOCUS, "trying pointer stuff");
if (allow_pointer && config_focus_follow)
if ((c = client_under_pointer()) &&
(allow_refocus || client_focus_target(c) != old) &&
(client_normal(c) &&
client_focus(c)))
{
- ob_debug_type(OB_DEBUG_FOCUS, "found in pointer stuff\n");
+ ob_debug_type(OB_DEBUG_FOCUS, "found in pointer stuff");
return c;
}
- ob_debug_type(OB_DEBUG_FOCUS, "trying the focus order\n");
+ ob_debug_type(OB_DEBUG_FOCUS, "trying the focus order");
for (it = focus_order; it; it = g_list_next(it)) {
c = it->data;
/* fallback focus to a window if:
3. it is not shaded
*/
if ((allow_omnipresent || c->desktop == screen_desktop) &&
- focus_valid_target(c, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) &&
+ focus_valid_target(c, screen_desktop,
+ TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
+ FALSE) &&
!c->shaded &&
(allow_refocus || client_focus_target(c) != old) &&
client_focus(c))
{
- ob_debug_type(OB_DEBUG_FOCUS, "found in focus order\n");
+ ob_debug_type(OB_DEBUG_FOCUS, "found in focus order");
return c;
}
}
- ob_debug_type(OB_DEBUG_FOCUS, "trying a desktop window\n");
+ ob_debug_type(OB_DEBUG_FOCUS, "trying a desktop window");
for (it = focus_order; it; it = g_list_next(it)) {
c = it->data;
/* fallback focus to a window if:
a splashscreen or a desktop window (save the desktop as a
backup fallback though)
*/
- if (focus_valid_target(c, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE) &&
+ if (focus_valid_target(c, screen_desktop,
+ TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE) &&
(allow_refocus || client_focus_target(c) != old) &&
client_focus(c))
{
- ob_debug_type(OB_DEBUG_FOCUS, "found a desktop window\n");
+ ob_debug_type(OB_DEBUG_FOCUS, "found a desktop window");
return c;
}
}
focus_set_client(NULL);
/* when nothing will be focused, send focus to the backup target */
- XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot,
+ XSetInputFocus(obt_display, screen_support_win, RevertToPointerRoot,
event_curtime);
}
focus_order_to_top(c);
else {
g_assert(!g_list_find(focus_order, c));
- /* if there are any iconic windows, put this above them in the order,
+ /* if there are only iconic windows, put this above them in the order,
but if there are not, then put it under the currently focused one */
if (focus_order && ((ObClient*)focus_order->data)->iconic)
focus_order = g_list_insert(focus_order, c, 0);
focus_order = g_list_insert(focus_order, c, 1);
}
- /* in the middle of cycling..? kill it. */
- focus_cycle_stop(c);
+ focus_cycle_addremove(c, TRUE);
}
void focus_order_remove(ObClient *c)
{
focus_order = g_list_remove(focus_order, c);
- /* in the middle of cycling..? kill it. */
- focus_cycle_stop(c);
+ focus_cycle_addremove(c, TRUE);
+}
+
+void focus_order_like_new(struct _ObClient *c)
+{
+ focus_order = g_list_remove(focus_order, c);
+ focus_order_add_new(c);
}
void focus_order_to_top(ObClient *c)
it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
focus_order = g_list_insert_before(focus_order, it, c);
}
+
+ focus_cycle_reorder();
}
void focus_order_to_bottom(ObClient *c)
it && !((ObClient*)it->data)->iconic; it = g_list_next(it));
focus_order = g_list_insert_before(focus_order, it, c);
}
+
+ focus_cycle_reorder();
}
ObClient *focus_order_find_first(guint desktop)
ObClient *c = it->data;
/* check that it's not a helper window to avoid infinite recursion */
if (c != ft && c->type == OB_CLIENT_TYPE_NORMAL &&
- focus_valid_target(c, TRUE, iconic_windows, all_desktops,
- FALSE, FALSE, FALSE))
+ focus_valid_target(c, screen_desktop,
+ TRUE, iconic_windows, all_desktops,
+ TRUE, FALSE, FALSE, FALSE))
{
return TRUE;
}
}
gboolean focus_valid_target(ObClient *ft,
+ guint desktop,
gboolean helper_windows,
gboolean iconic_windows,
gboolean all_desktops,
+ gboolean nonhilite_windows,
gboolean dock_windows,
gboolean desktop_windows,
gboolean user_request)
{
+ /* NOTE: if any of these things change on a client, then they should call
+ focus_cycle_addremove() to make sure the client is not shown/hidden
+ when it should not be */
+
gboolean ok = FALSE;
+ /* see if the window is still managed or is going away */
+ if (!ft->managed) return FALSE;
+
/* it's on this desktop unless you want all desktops.
do this check first because it will usually filter out the most
windows */
- ok = (all_desktops || ft->desktop == screen_desktop ||
+ ok = (all_desktops || ft->desktop == desktop ||
ft->desktop == DESKTOP_ALL);
+ /* if we only include hilited windows, check if the window is */
+ ok = ok && (nonhilite_windows || ft->demands_attention);
+
/* the window can receive focus somehow */
ok = ok && (ft->can_focus || ft->focus_notify);
that can be focused instead */
!focus_target_has_siblings(ft, iconic_windows, all_desktops))));
- /* it's not set to skip the taskbar (but this only applies to normal typed
- windows, and is overridden if the window is modal or if the user asked
- for this window to be focused) */
- ok = ok && (ft->type != OB_CLIENT_TYPE_NORMAL ||
- ft->modal ||
- user_request ||
- !ft->skip_taskbar);
+ /* it's not set to skip the taskbar (but this is overridden if the
+ window is modal or if the user asked for this window to be focused,
+ or if the window is iconified (and does not have any parents with
+ which to uniconify it), and it is not used for windows which are
+ hilited, or dialog windows as these need user interaction and should
+ not be long-lasting windows */
+ ok = ok && (!ft->skip_taskbar ||
+ (ft->modal || user_request ||
+ (ft->iconic && !ft->parents) ||
+ ft->demands_attention ||
+ ft->type == OB_CLIENT_TYPE_DIALOG));
/* it's not going to just send focus off somewhere else (modal window),
unless that modal window is not one of our valid targets, then let
{
ObClient *cft = client_focus_target(ft);
ok = ok && (ft == cft || !focus_valid_target(cft,
+ screen_desktop,
TRUE,
iconic_windows,
all_desktops,
+ nonhilite_windows,
dock_windows,
desktop_windows,
FALSE));