]> git.sur5r.net Git - i3/i3/blobdiff - src/con.c
Raise floating window to top when it gets focus
[i3/i3] / src / con.c
index 136ce5d2a8f7a007d29a4e46f8287bdb80128dc8..df6a8437e895ffdb475ce2034a017288bdeaae15 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -73,6 +73,30 @@ Con *con_new(Con *parent, i3Window *window) {
     return new;
 }
 
+/*
+ * Frees the specified container.
+ *
+ */
+void con_free(Con *con) {
+    free(con->name);
+    FREE(con->deco_render_params);
+    TAILQ_REMOVE(&all_cons, con, all_cons);
+    while (!TAILQ_EMPTY(&(con->swallow_head))) {
+        Match *match = TAILQ_FIRST(&(con->swallow_head));
+        TAILQ_REMOVE(&(con->swallow_head), match, matches);
+        match_free(match);
+        free(match);
+    }
+    while (!TAILQ_EMPTY(&(con->marks_head))) {
+        mark_t *mark = TAILQ_FIRST(&(con->marks_head));
+        TAILQ_REMOVE(&(con->marks_head), mark, marks);
+        FREE(mark->name);
+        FREE(mark);
+    }
+    free(con);
+    DLOG("con %p freed\n", con);
+}
+
 static void _con_attach(Con *con, Con *parent, Con *previous, bool ignore_focus) {
     con->parent = parent;
     Con *loop;
@@ -219,6 +243,13 @@ 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);
+    }
 }
 
 /*
@@ -379,7 +410,7 @@ Con *con_get_workspace(Con *con) {
 }
 
 /*
- * Searches parenst of the given 'con' until it reaches one with the specified
+ * Searches parents of the given 'con' until it reaches one with the specified
  * 'orientation'. Aborts when it comes across a floating_con.
  *
  */
@@ -557,6 +588,22 @@ Con *con_by_window_id(xcb_window_t window) {
     return NULL;
 }
 
+/*
+ * Returns the container with the given container ID or NULL if no such
+ * container exists.
+ *
+ */
+Con *con_by_con_id(long target) {
+    Con *con;
+    TAILQ_FOREACH(con, &all_cons, all_cons) {
+        if (con == (Con *)target) {
+            return con;
+        }
+    }
+
+    return NULL;
+}
+
 /*
  * Returns the container with the given frame ID or NULL if no such container
  * exists.
@@ -1105,8 +1152,13 @@ static bool _con_move_to_con(Con *con, Con *target, bool behind_focused, bool fi
     /* Descend focus stack in case focus_next is a workspace which can
      * occur if we move to the same workspace.  Also show current workspace
      * to ensure it is focused. */
-    if (!ignore_focus)
+    if (!ignore_focus) {
         workspace_show(current_ws);
+        if (dont_warp) {
+            DLOG("x_set_warp_to(NULL) because dont_warp is set\n");
+            x_set_warp_to(NULL);
+        }
+    }
 
     /* Set focus only if con was on current workspace before moving.
      * Otherwise we would give focus to some window on different workspace. */
@@ -1239,12 +1291,33 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
  * visible workspace on the given output.
  *
  */
-void con_move_to_output(Con *con, Output *output) {
+void con_move_to_output(Con *con, Output *output, bool fix_coordinates) {
     Con *ws = NULL;
     GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
     assert(ws != NULL);
-    DLOG("Moving con %p to output %s\n", con, output->name);
-    con_move_to_workspace(con, ws, false, false, false);
+    DLOG("Moving con %p to output %s\n", con, output_primary_name(output));
+    con_move_to_workspace(con, ws, fix_coordinates, false, false);
+}
+
+/*
+ * Moves the given container to the currently focused container on the
+ * visible workspace on the output specified by the given name.
+ * The current output for the container is used to resolve relative names
+ * such as left, right, up, down.
+ *
+ */
+bool con_move_to_output_name(Con *con, const char *name, bool fix_coordinates) {
+    Output *current_output = get_output_for_con(con);
+    assert(current_output != NULL);
+
+    Output *output = get_output_from_string(current_output, name);
+    if (output == NULL) {
+        ELOG("Could not find output \"%s\"\n", name);
+        return false;
+    }
+
+    con_move_to_output(con, output, fix_coordinates);
+    return true;
 }
 
 /*
@@ -1796,7 +1869,9 @@ void con_toggle_layout(Con *con, const char *toggle_mode) {
             }
         }
 
-        con_set_layout(con, new_layout);
+        if (new_layout != L_DEFAULT) {
+            con_set_layout(con, new_layout);
+        }
     } else if (strcasecmp(toggle_mode, "all") == 0 || strcasecmp(toggle_mode, "default") == 0) {
         if (parent->layout == L_STACKED)
             con_set_layout(con, L_TABBED);
@@ -2231,15 +2306,14 @@ bool con_swap(Con *first, Con *second) {
     Con *current_ws = con_get_workspace(old_focus);
     const bool focused_within_first = (first == old_focus || con_has_parent(old_focus, first));
     const bool focused_within_second = (second == old_focus || con_has_parent(old_focus, second));
+    fullscreen_mode_t first_fullscreen_mode = first->fullscreen_mode;
+    fullscreen_mode_t second_fullscreen_mode = second->fullscreen_mode;
 
-    if (!con_fullscreen_permits_focusing(first_ws)) {
-        DLOG("Cannot swap because target workspace \"%s\" is obscured.\n", first_ws->name);
-        return false;
+    if (first_fullscreen_mode != CF_NONE) {
+        con_disable_fullscreen(first);
     }
-
-    if (!con_fullscreen_permits_focusing(second_ws)) {
-        DLOG("Cannot swap because target workspace \"%s\" is obscured.\n", second_ws->name);
-        return false;
+    if (second_fullscreen_mode != CF_NONE) {
+        con_disable_fullscreen(second);
     }
 
     double first_percent = first->percent;
@@ -2340,7 +2414,17 @@ bool con_swap(Con *first, Con *second) {
     second->percent = first_percent;
     fake->percent = 0.0;
 
+    SWAP(first_fullscreen_mode, second_fullscreen_mode, fullscreen_mode_t);
+
 swap_end:
+    /* The two windows exchange their original fullscreen status */
+    if (first_fullscreen_mode != CF_NONE) {
+        con_enable_fullscreen(first, first_fullscreen_mode);
+    }
+    if (second_fullscreen_mode != CF_NONE) {
+        con_enable_fullscreen(second, second_fullscreen_mode);
+    }
+
     /* We don't actually need this since percentages-wise we haven't changed
      * anything, but we'll better be safe than sorry and just make sure as we'd
      * otherwise crash i3. */