]> git.sur5r.net Git - i3/i3/commitdiff
Don't raise floating windows when focused because of focus_follows_mouse 2998/head
authorOrestis Floros <orestisf1993@gmail.com>
Tue, 5 Dec 2017 23:58:47 +0000 (01:58 +0200)
committerOrestis Floros <orestisf1993@gmail.com>
Sun, 14 Jan 2018 13:45:33 +0000 (15:45 +0200)
Fixes #2990.

15 files changed:
include/con.h
src/click.c
src/commands.c
src/con.c
src/floating.c
src/handlers.c
src/load_layout.c
src/main.c
src/manage.c
src/move.c
src/randr.c
src/scratchpad.c
src/tree.c
src/workspace.c
testcases/t/293-focus-follows-mouse.t

index b88ea354cd7e0b28e754ed0ac3e97167026d1916..726fec96d145e501898d2793367a3d1572eaa269 100644 (file)
@@ -38,6 +38,12 @@ void con_free(Con *con);
  */
 void con_focus(Con *con);
 
+/**
+ * Sets input focus to the given container and raises it to the top.
+ *
+ */
+void con_activate(Con *con);
+
 /**
  * Closes the given container.
  *
index 78af8a0350cd067179f5aaedcf263ad631e11b84..5b529a383a6b00eb3ccc5d83b1005c96bf9ffd8a 100644 (file)
@@ -241,7 +241,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
          * The splitv container will be focused. */
         Con *focused = con->parent;
         focused = TAILQ_FIRST(&(focused->focus_head));
-        con_focus(focused);
+        con_activate(focused);
         /* To prevent scrolling from going outside the container (see ticket
          * #557), we first check if scrolling is possible at all. */
         bool scroll_prev_possible = (TAILQ_PREV(focused, nodes_head, nodes) != NULL);
@@ -256,7 +256,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
     }
 
     /* 2: focus this con. */
-    con_focus(con);
+    con_activate(con);
 
     /* 3: For floating containers, we also want to raise them on click.
      * We will skip handling events on floating cons in fullscreen mode */
index 162f0892f4105941afe19aa33d2726c997b3c4f4..df2b236b10d23423074d3bbd0608b3b429a1b927 100644 (file)
@@ -1261,7 +1261,7 @@ static void cmd_focus_force_focus(Con *con) {
     if (fullscreen_on_ws && fullscreen_on_ws != con && !con_has_parent(con, fullscreen_on_ws)) {
         con_disable_fullscreen(fullscreen_on_ws);
     }
-    con_focus(con);
+    con_activate(con);
 }
 
 /*
@@ -1379,12 +1379,12 @@ void cmd_focus(I3_CMD) {
          * the target workspace, then revert focus. */
         Con *currently_focused = focused;
         cmd_focus_force_focus(current->con);
-        con_focus(currently_focused);
+        con_activate(currently_focused);
 
         /* Now switch to the workspace, then focus */
         workspace_show(ws);
         LOG("focusing %p / %s\n", current->con, current->con->name);
-        con_focus(current->con);
+        con_activate(current->con);
         count++;
     }
 
@@ -1496,7 +1496,7 @@ void cmd_move_direction(I3_CMD, const char *direction, long move_px) {
 
     /* the move command should not disturb focus */
     if (focused != initially_focused)
-        con_focus(initially_focused);
+        con_activate(initially_focused);
 
     // XXX: default reply for now, make this a better reply
     ysuccess(true);
@@ -1621,7 +1621,7 @@ void cmd_open(I3_CMD) {
     LOG("opening new container\n");
     Con *con = tree_open_con(NULL, NULL);
     con->layout = L_SPLITH;
-    con_focus(con);
+    con_activate(con);
 
     y(map_open);
     ystr("success");
@@ -2010,7 +2010,7 @@ void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
     }
 
     /* Restore the previous focus since con_attach messes with the focus. */
-    con_focus(previously_focused);
+    con_activate(previously_focused);
 
     cmd_output->needs_tree_render = true;
     ysuccess(true);
index c9e2b6cfa076f819e2d32e31a474d4927625f103..2d9b8691bd021ad67c5172579cdb1da24a88ca85 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -243,15 +243,29 @@ void con_focus(Con *con) {
         workspace_update_urgent_flag(con_get_workspace(con));
         ipc_send_window_event("urgent", con);
     }
+}
 
-    /* Focusing a container with a floating parent should raise it to the top. Since
-     * con_focus is called recursively for each parent we don't need to use
-     * con_inside_floating(). */
-    if (con->type == CT_FLOATING_CON) {
-        floating_raise_con(con);
+/*
+ * Raise container to the top if it is floating or inside some floating
+ * container.
+ *
+ */
+static void con_raise(Con *con) {
+    Con *floating = con_inside_floating(con);
+    if (floating) {
+        floating_raise_con(floating);
     }
 }
 
+/*
+ * Sets input focus to the given container and raises it to the top.
+ *
+ */
+void con_activate(Con *con) {
+    con_focus(con);
+    con_raise(con);
+}
+
 /*
  * Closes the given container.
  *
@@ -994,9 +1008,9 @@ void con_enable_fullscreen(Con *con, fullscreen_mode_t fullscreen_mode) {
     Con *old_focused = focused;
     if (fullscreen_mode == CF_GLOBAL && cur_ws != con_ws)
         workspace_show(con_ws);
-    con_focus(con);
+    con_activate(con);
     if (fullscreen_mode != CF_GLOBAL && cur_ws != con_ws)
-        con_focus(old_focused);
+        con_activate(old_focused);
 
     con_set_fullscreen_mode(con, fullscreen_mode);
 }
@@ -1148,11 +1162,11 @@ static bool _con_move_to_con(Con *con, Con *target, bool behind_focused, bool fi
          * new workspace is hidden and it's necessary to immediately switch
          * back to the originally-focused workspace. */
         Con *old_focus = TAILQ_FIRST(&(output_get_content(dest_output)->focus_head));
-        con_focus(con_descend_focused(con));
+        con_activate(con_descend_focused(con));
 
         /* Restore focus if the output's focused workspace has changed. */
         if (con_get_workspace(focused) != old_focus)
-            con_focus(old_focus);
+            con_activate(old_focus);
     }
 
     /* 7: when moving to another workspace, we leave the focus on the current
@@ -1172,7 +1186,7 @@ static bool _con_move_to_con(Con *con, Con *target, bool behind_focused, bool fi
     /* Set focus only if con was on current workspace before moving.
      * Otherwise we would give focus to some window on different workspace. */
     if (!ignore_focus && source_ws == current_ws)
-        con_focus(con_descend_focused(focus_next));
+        con_activate(con_descend_focused(focus_next));
 
     /* 8. If anything within the container is associated with a startup sequence,
      * delete it so child windows won't be created on the old workspace. */
@@ -1791,7 +1805,7 @@ void con_set_layout(Con *con, layout_t layout) {
             con_attach(new, con, false);
 
             if (old_focused)
-                con_focus(old_focused);
+                con_activate(old_focused);
 
             tree_flatten(croot);
         }
@@ -2358,7 +2372,7 @@ bool con_swap(Con *first, Con *second) {
      * We don't need to check this for the second container because we've only
      * moved the first one at this point.*/
     if (first_ws != second_ws && focused_within_first) {
-        con_focus(con_descend_focused(current_ws));
+        con_activate(con_descend_focused(current_ws));
     }
 
     /* Move second to where first has been originally. */
@@ -2401,15 +2415,15 @@ bool con_swap(Con *first, Con *second) {
      */
     if (focused_within_first) {
         if (first_ws == second_ws) {
-            con_focus(old_focus);
+            con_activate(old_focus);
         } else {
-            con_focus(con_descend_focused(second));
+            con_activate(con_descend_focused(second));
         }
     } else if (focused_within_second) {
         if (first_ws == second_ws) {
-            con_focus(old_focus);
+            con_activate(old_focus);
         } else {
-            con_focus(con_descend_focused(first));
+            con_activate(con_descend_focused(first));
         }
     }
 
index 85bd8cc051370dc0f3d95f3922df50212425b1cb..e958153d6a647ab5242188d932f28e1b3ae19e98 100644 (file)
@@ -318,7 +318,7 @@ void floating_enable(Con *con, bool automatic) {
     render_con(con, false);
 
     if (set_focus)
-        con_focus(con);
+        con_activate(con);
 
     /* Check if we need to re-assign it to a different workspace because of its
      * coordinates and exit if that was done successfully. */
@@ -382,7 +382,7 @@ void floating_disable(Con *con, bool automatic) {
     con_fix_percent(con->parent);
 
     if (set_focus)
-        con_focus(con);
+        con_activate(con);
 
     floating_set_hint_atom(con, false);
     ipc_send_window_event("floating", con);
@@ -450,7 +450,7 @@ bool floating_maybe_reassign_ws(Con *con) {
     DLOG("Moving con %p / %s to workspace %p / %s\n", con, con->name, ws, ws->name);
     con_move_to_workspace(con, ws, false, true, false);
     workspace_show(ws);
-    con_focus(con_descend_focused(con));
+    con_activate(con_descend_focused(con));
     return true;
 }
 
index 0f81afae19a095233e4c568e0b8dff7667edeb8b..e1671c3b4bec2df918fdf70d89d38a29ee77c0d1 100644 (file)
@@ -433,7 +433,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
         if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(ws))) {
             DLOG("Focusing con = %p\n", con);
             workspace_show(ws);
-            con_focus(con);
+            con_activate(con);
             tree_render();
         } else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(ws))) {
             DLOG("Marking con = %p urgent\n", con);
@@ -776,7 +776,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
                 workspace_show(ws);
                 /* Re-set focus, even if unchanged from i3’s perspective. */
                 focused_id = XCB_NONE;
-                con_focus(con);
+                con_activate(con);
             }
         } else {
             /* Request is from an application. */
@@ -788,7 +788,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
             if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(ws))) {
                 DLOG("Focusing con = %p\n", con);
                 workspace_show(ws);
-                con_focus(con);
+                con_activate(con);
             } else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(ws))) {
                 DLOG("Marking con = %p urgent\n", con);
                 con_set_urgency(con, true);
@@ -1245,7 +1245,7 @@ static void handle_focus_in(xcb_focus_in_event_t *event) {
     if (ws != con_get_workspace(focused))
         workspace_show(ws);
 
-    con_focus(con);
+    con_activate(con);
     /* We update focused_id because we don’t need to set focus again */
     focused_id = event->event;
     tree_render();
index 071b3ccd650a1833fbf4efdb4d7d91fe4649dff2..aa7ac03c452f20c66505215602be441cc61ae3bd 100644 (file)
@@ -654,6 +654,6 @@ void tree_append_json(Con *con, const char *buf, const size_t len, char **errorm
     yajl_free(hand);
 
     if (to_focus) {
-        con_focus(to_focus);
+        con_activate(to_focus);
     }
 }
index b634b139f90276db0e4273d28a70922f732a63f5..194ef05c337efc76898d780eee8148f5fc9c9ca0 100644 (file)
@@ -766,7 +766,7 @@ int main(int argc, char *argv[]) {
             output = get_first_output();
         }
 
-        con_focus(con_descend_focused(output_get_content(output->con)));
+        con_activate(con_descend_focused(output_get_content(output->con)));
         free(pointerreply);
     }
 
index d12ce8d6e11c8b475bc0068738df87994f2b032b..8b306052c7ea77243e457ccf97bccbd25ac0f23c 100644 (file)
@@ -646,7 +646,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
      * proper window event sequence. */
     if (set_focus && nc->mapped) {
         DLOG("Now setting focus.\n");
-        con_focus(nc);
+        con_activate(nc);
     }
 
     tree_render();
index 3ecc69e4c762c7c63e2e38ab6a9ceadaeb91edf0..97ca6d40b42423a07582d44f3ade0f9001d7ef7f 100644 (file)
@@ -118,7 +118,7 @@ static void move_to_output_directed(Con *con, direction_t direction) {
     attach_to_workspace(con, ws, direction);
 
     /* fix the focus stack */
-    con_focus(con);
+    con_activate(con);
 
     /* force re-painting the indicators */
     FREE(con->deco_render_params);
index 1d3330145dfb7fe62c1d3db041fa9514614214cd..85add08fa41ea2cb64a60fc194a3fe65d02a1550 100644 (file)
@@ -496,7 +496,7 @@ void init_ws_for_output(Output *output, Con *content) {
     Con *ws = create_workspace_on_output(output, content);
 
     /* TODO: Set focus in main.c */
-    con_focus(ws);
+    con_activate(ws);
 }
 
 /*
@@ -924,7 +924,7 @@ void randr_query_outputs(void) {
             continue;
 
         DLOG("Focusing primary output %s\n", output_primary_name(output));
-        con_focus(con_descend_focused(output->con));
+        con_activate(con_descend_focused(output->con));
     }
 
     /* render_layout flushes */
@@ -987,7 +987,7 @@ void randr_disable_output(Output *output) {
 
         if (next) {
             DLOG("now focusing next = %p\n", next);
-            con_focus(next);
+            con_activate(next);
             workspace_show(con_get_workspace(next));
         }
 
index 9018ad3ffc233c0037b000eb40837f58cf8a3f41..95154014c729a655a40b4ab9be49dd42f815eedf 100644 (file)
@@ -123,7 +123,7 @@ void scratchpad_show(Con *con) {
             /* use con_descend_tiling_focused to get the last focused
                  * window inside this scratch container in order to
                  * keep the focus the same within this container */
-            con_focus(con_descend_tiling_focused(walk_con));
+            con_activate(con_descend_tiling_focused(walk_con));
             return;
         }
     }
@@ -205,7 +205,7 @@ void scratchpad_show(Con *con) {
         workspace_show(active);
     }
 
-    con_focus(con_descend_focused(con));
+    con_activate(con_descend_focused(con));
 }
 
 /*
index d1c587d5b9d7de97a4a098b9cef4882428cfc505..b8bc732bca6625f8d27f2c9624cebfa2d73eebea 100644 (file)
@@ -344,12 +344,12 @@ bool tree_close_internal(Con *con, kill_window_t kill_window, bool dont_kill_par
             DLOG("focusing %p / %s\n", next, next->name);
             if (next->type == CT_DOCKAREA) {
                 /* Instead of focusing the dockarea, we need to restore focus to the workspace */
-                con_focus(con_descend_focused(output_get_content(next->parent)));
+                con_activate(con_descend_focused(output_get_content(next->parent)));
             } else {
                 if (!force_set_focus && con != focused)
                     DLOG("not changing focus, the container was not focused before\n");
                 else
-                    con_focus(next);
+                    con_activate(next);
             }
         } else {
             DLOG("not focusing because we're not killing anybody\n");
@@ -433,7 +433,7 @@ bool level_up(void) {
     /* Skip over floating containers and go directly to the grandparent
      * (which should always be a workspace) */
     if (focused->parent->type == CT_FLOATING_CON) {
-        con_focus(focused->parent->parent);
+        con_activate(focused->parent->parent);
         return true;
     }
 
@@ -444,7 +444,7 @@ bool level_up(void) {
         ELOG("'focus parent': Focus is already on the workspace, cannot go higher than that.\n");
         return false;
     }
-    con_focus(focused->parent);
+    con_activate(focused->parent);
     return true;
 }
 
@@ -469,7 +469,7 @@ bool level_down(void) {
             next = TAILQ_FIRST(&(next->focus_head));
     }
 
-    con_focus(next);
+    con_activate(next);
     return true;
 }
 
@@ -566,7 +566,7 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap)
         }
 
         workspace_show(workspace);
-        con_focus(focus);
+        con_activate(focus);
         x_set_warp_to(&(focus->rect));
         return true;
     }
@@ -604,7 +604,7 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap)
             TAILQ_INSERT_HEAD(&(parent->floating_head), last, floating_windows);
         }
 
-        con_focus(con_descend_focused(next));
+        con_activate(con_descend_focused(next));
         return true;
     }
 
@@ -653,7 +653,7 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap)
     /* 3: focus choice comes in here. at the moment we will go down
      * until we find a window */
     /* TODO: check for window, atm we only go down as far as possible */
-    con_focus(con_descend_focused(next));
+    con_activate(con_descend_focused(next));
     return true;
 }
 
index 1531335765dff19438ac1ba3857a3f4d84d13b65..d200b6e43fd391d0244ba2aff6d05af01b6fd911 100644 (file)
@@ -412,7 +412,7 @@ static void _workspace_show(Con *workspace) {
     if (next->urgent && (int)(config.workspace_urgency_timer * 1000) > 0) {
         /* focus for now… */
         next->urgent = false;
-        con_focus(next);
+        con_activate(next);
 
         /* … but immediately reset urgency flags; they will be set to false by
          * the timer callback in case the container is focused at the time of
@@ -435,7 +435,7 @@ static void _workspace_show(Con *workspace) {
             ev_timer_again(main_loop, focused->urgency_timer);
         }
     } else
-        con_focus(next);
+        con_activate(next);
 
     ipc_send_workspace_event("focus", workspace, current);
 
@@ -837,7 +837,7 @@ void ws_force_orientation(Con *ws, orientation_t orientation) {
     con_fix_percent(ws);
 
     if (old_focused)
-        con_focus(old_focused);
+        con_activate(old_focused);
 }
 
 /*
index 9fb1004e6af14636a2f73cf88ea61a8ddc557e07..0cd6e5c3228f72d405237eb4a55ba6d7351f05c6 100644 (file)
@@ -57,4 +57,32 @@ is($x->input_focus, $second->id, 'second (tabbed) window focused');
 synced_warp_pointer(0, 0);
 is($x->input_focus, $second->id, 'second window still focused');
 
+###################################################################
+# Test that floating windows are focused but not raised to the top.
+# See issue #2990.
+###################################################################
+
+my $ws;
+my $tmp = fresh_workspace;
+my ($first_floating, $second_floating);
+
+synced_warp_pointer(0, 0);
+$first_floating = open_floating_window;
+$first_floating->rect(X11::XCB::Rect->new(x => 1, y => 1, width => 100, height => 100));
+$second_floating = open_floating_window;
+$second_floating->rect(X11::XCB::Rect->new(x => 50, y => 50, width => 100, height => 100));
+sync_with_i3;
+$first = open_window;
+
+is($x->input_focus, $first->id, 'first (tiling) window focused');
+$ws = get_ws($tmp);
+is($ws->{floating_nodes}->[1]->{nodes}->[0]->{window}, $second_floating->id, 'second floating on top');
+is($ws->{floating_nodes}->[0]->{nodes}->[0]->{window}, $first_floating->id, 'first floating behind');
+
+synced_warp_pointer(40, 40);
+is($x->input_focus, $first_floating->id, 'first floating window focused');
+$ws = get_ws($tmp);
+is($ws->{floating_nodes}->[1]->{nodes}->[0]->{window}, $second_floating->id, 'second floating still on top');
+is($ws->{floating_nodes}->[0]->{nodes}->[0]->{window}, $first_floating->id, 'first floating still behind');
+
 done_testing;