]> git.sur5r.net Git - i3/i3/blobdiff - src/commands.c
Bugfix: Don’t set focus if it is not necessary.
[i3/i3] / src / commands.c
index 4e9f304aedaf9a0c430e8444faeff84c6bcf2b60..258d5a0925d00baf5e1751609b1d23b93628d30a 100644 (file)
@@ -24,8 +24,7 @@
 #include "i3.h"
 #include "xinerama.h"
 
-static bool focus_window_in_container(xcb_connection_t *conn, Container *container,
-                direction_t direction) {
+bool focus_window_in_container(xcb_connection_t *conn, Container *container, direction_t direction) {
         /* If this container is empty, we’re done */
         if (container->currently_focused == NULL)
                 return false;
@@ -46,7 +45,7 @@ static bool focus_window_in_container(xcb_connection_t *conn, Container *contain
                 return false;
 
         /* Set focus */
-        set_focus(conn, candidate);
+        set_focus(conn, candidate, true);
 
         return true;
 }
@@ -123,7 +122,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
                 new_row = (t_ws->rows - 1);
 
         if (t_ws->table[new_col][new_row]->currently_focused != NULL)
-                set_focus(conn, t_ws->table[new_col][new_row]->currently_focused);
+                set_focus(conn, t_ws->table[new_col][new_row]->currently_focused, true);
 }
 
 /*
@@ -219,6 +218,7 @@ static void move_current_window(xcb_connection_t *conn, direction_t direction) {
         /* Remove it from the old container and put it into the new one */
         remove_client_from_container(conn, current_client, container);
         CIRCLEQ_INSERT_TAIL(&(new->clients), current_client, clients);
+        SLIST_INSERT_HEAD(&(new->workspace->focus_stack), current_client, focus_clients);
 
         /* Update data structures */
         current_client->container = new;
@@ -235,7 +235,7 @@ static void move_current_window(xcb_connection_t *conn, direction_t direction) {
 
         render_layout(conn);
 
-        set_focus(conn, current_client);
+        set_focus(conn, current_client, true);
 }
 
 static void move_current_container(xcb_connection_t *conn, direction_t direction) {
@@ -424,8 +424,7 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa
 
         assert(to_container != NULL);
 
-        CIRCLEQ_REMOVE(&(container->clients), current_client, clients);
-        SLIST_REMOVE(&(container->workspace->focus_stack), current_client, Client, focus_clients);
+        remove_client_from_container(conn, current_client, container);
 
         CIRCLEQ_INSERT_TAIL(&(to_container->clients), current_client, clients);
         SLIST_INSERT_HEAD(&(to_container->workspace->focus_stack), current_client, focus_clients);
@@ -447,7 +446,11 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa
         render_layout(conn);
 }
 
-static void show_workspace(xcb_connection_t *conn, int workspace) {
+/*
+ * Switches to the given workspace
+ *
+ */
+void show_workspace(xcb_connection_t *conn, int workspace) {
         Client *client;
         xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(conn)).data->root;
         /* t_ws (to workspace) is just a convenience pointer to the workspace we’re switching to */
@@ -470,6 +473,10 @@ static void show_workspace(xcb_connection_t *conn, int workspace) {
         if (c_ws->screen != t_ws->screen) {
                 /* We need to switch to the other screen first */
                 LOG("moving over to other screen.\n");
+
+                /* Store the old client */
+                Client *old_client = CUR_CELL->currently_focused;
+
                 c_ws = &(workspaces[t_ws->screen->current_workspace]);
                 current_col = c_ws->current_col;
                 current_row = c_ws->current_row;
@@ -480,6 +487,11 @@ static void show_workspace(xcb_connection_t *conn, int workspace) {
                         xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0,
                                          dims->x + (dims->width / 2), dims->y + (dims->height / 2));
                 }
+
+                /* Re-decorate the old client, it’s not focused anymore */
+                if ((old_client != NULL) && !old_client->dock)
+                        redecorate_window(conn, old_client);
+                else xcb_flush(conn);
         }
 
         /* Check if we need to change something or if we’re already there */
@@ -534,7 +546,7 @@ static void show_workspace(xcb_connection_t *conn, int workspace) {
 
         /* Restore focus on the new workspace */
         if (CUR_CELL->currently_focused != NULL)
-                set_focus(conn, CUR_CELL->currently_focused);
+                set_focus(conn, CUR_CELL->currently_focused, true);
         else xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, root, XCB_CURRENT_TIME);
 
         //xcb_ungrab_server(conn);
@@ -552,20 +564,37 @@ void parse_command(xcb_connection_t *conn, const char *command) {
         if (command[0] == '\0')
                 return;
 
-        /* Is it an <exec>? */
-        if (strncmp(command, "exec ", strlen("exec ")) == 0) {
+        /* Is it an <exec>? Then execute the given command. */
+        if (STARTS_WITH(command, "exec ")) {
                 LOG("starting \"%s\"\n", command + strlen("exec "));
                 start_application(command+strlen("exec "));
                 return;
         }
 
-        /* Is it <restart>? */
-        if (strncmp(command, "restart", strlen("restart")) == 0) {
+        /* Is it an <exit>? */
+        if (STARTS_WITH(command, "exit")) {
+                LOG("User issued exit-command, exiting without error.\n");
+                exit(EXIT_SUCCESS);
+        }
+
+        /* Is it <restart>? Then restart in place. */
+        if (STARTS_WITH(command, "restart")) {
                 LOG("restarting \"%s\"...\n", application_path);
                 execl(application_path, application_path, NULL);
                 /* not reached */
         }
 
+        if (STARTS_WITH(command, "kill")) {
+                if (CUR_CELL->currently_focused == NULL) {
+                        LOG("There is no window to kill\n");
+                        return;
+                }
+
+                LOG("Killing current window\n");
+                kill_window(conn, CUR_CELL->currently_focused);
+                return;
+        }
+
         /* Is it 'f' for fullscreen? */
         if (command[0] == 'f') {
                 if (CUR_CELL->currently_focused == NULL)