Suppress no_focus for first window on a workspace.

With this patch, the no_focus directive will be ignored if the
to-be-opened window is the first on its workspace as there's no
reason the user would not want to focus it in this case.
This improves usability when, for example, using a tabbed
workspace_layout.

fixes #1987
This commit is contained in:
Ingo Bürk 2015-10-12 12:56:19 +02:00
parent d24964ff6a
commit f7907c11d7
3 changed files with 46 additions and 6 deletions

View File

@ -610,6 +610,10 @@ Note that this does not apply to all cases, e.g., when feeding data into a runni
causing it to request being focused. To configure the behavior in such cases, refer to causing it to request being focused. To configure the behavior in such cases, refer to
<<focus_on_window_activation>>. <<focus_on_window_activation>>.
+no_focus+ will also be ignored for the first window on a workspace as there shouldn't be
a reason to not focus the window in this case. This allows for better usability in
combination with +workspace_layout+.
*Syntax*: *Syntax*:
------------------- -------------------
no_focus <criteria> no_focus <criteria>

View File

@ -524,13 +524,23 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
/* Send an event about window creation */ /* Send an event about window creation */
ipc_send_window_event("new", nc); ipc_send_window_event("new", nc);
if (set_focus && assignment_for(cwindow, A_NO_FOCUS) != NULL) {
/* The first window on a workspace should always be focused. We have to
* compare with == 1 because the container has already been inserted at
* this point. */
if (con_num_children(ws) == 1) {
DLOG("This is the first window on this workspace, ignoring no_focus.\n");
} else {
DLOG("no_focus was set for con = %p, not setting focus.\n", nc);
set_focus = false;
}
}
/* Defer setting focus after the 'new' event has been sent to ensure the /* Defer setting focus after the 'new' event has been sent to ensure the
* proper window event sequence. */ * proper window event sequence. */
if (set_focus && !nc->window->doesnt_accept_focus && nc->mapped) { if (set_focus && !nc->window->doesnt_accept_focus && nc->mapped) {
if (assignment_for(cwindow, A_NO_FOCUS) == NULL) { DLOG("Now setting focus.\n");
DLOG("Now setting focus.\n"); con_focus(nc);
con_focus(nc);
}
} }
tree_render(); tree_render();

View File

@ -30,13 +30,15 @@ font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
EOT EOT
$pid = launch_with_config($config); $pid = launch_with_config($config);
$ws = fresh_workspace; $ws = fresh_workspace;
$first = open_window; $first = open_window;
$focused = get_focused($ws); $focused = get_focused($ws);
$second = open_window; $second = open_window;
sync_with_i3;
isnt(get_focused($ws), $focused, 'focus has changed'); isnt(get_focused($ws), $focused, 'focus has changed');
is($x->input_focus, $second->id, 'input focus has changed');
exit_gracefully($pid); exit_gracefully($pid);
@ -53,13 +55,37 @@ no_focus [instance=notme]
EOT EOT
$pid = launch_with_config($config); $pid = launch_with_config($config);
$ws = fresh_workspace; $ws = fresh_workspace;
$first = open_window; $first = open_window;
$focused = get_focused($ws); $focused = get_focused($ws);
$second = open_window(wm_class => 'notme'); $second = open_window(wm_class => 'notme');
sync_with_i3;
is(get_focused($ws), $focused, 'focus has not changed'); is(get_focused($ws), $focused, 'focus has not changed');
is($x->input_focus, $first->id, 'input focus has not changed');
exit_gracefully($pid);
#####################################################################
## 3: no_focus doesn't affect the first window opened on a workspace
#####################################################################
$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
no_focus [instance=focusme]
EOT
$pid = launch_with_config($config);
$ws = fresh_workspace;
$focused = get_focused($ws);
$first = open_window(wm_class => 'focusme');
sync_with_i3;
is($x->input_focus, $first->id, 'input focus has changed');
exit_gracefully($pid); exit_gracefully($pid);