X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcommands.c;h=2d8155f276a162494db56b6ce416566875b2861a;hb=a0e33c1d683ffe3b67a3967980f61f828b41fef2;hp=4317b36f6dd4a84aef40a7c9682cfee5b99edb5b;hpb=8d648b4e371cd7959a332d80aa288a3fa390cc7e;p=i3%2Fi3 diff --git a/src/commands.c b/src/commands.c index 4317b36f..2d8155f2 100644 --- a/src/commands.c +++ b/src/commands.c @@ -33,6 +33,7 @@ #include "log.h" #include "sighandler.h" #include "manage.h" +#include "ipc.h" bool focus_window_in_container(xcb_connection_t *conn, Container *container, direction_t direction) { /* If this container is empty, we’re done */ @@ -89,12 +90,13 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t Workspace *t_ws = c_ws; /* Makes sure new_col and new_row are within bounds of the new workspace */ - void check_colrow_boundaries() { - if (new_col >= t_ws->cols) - new_col = (t_ws->cols - 1); - if (new_row >= t_ws->rows) - new_row = (t_ws->rows - 1); - } +#define CHECK_COLROW_BOUNDARIES \ + do { \ + if (new_col >= t_ws->cols) \ + new_col = (t_ws->cols - 1); \ + if (new_row >= t_ws->rows) \ + new_row = (t_ws->rows - 1); \ + } while (0) /* There always is a container. If not, current_col or current_row is wrong */ assert(container != NULL); @@ -174,7 +176,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t new_row = (direction == D_UP ? (t_ws->rows - 1) : 0); } - check_colrow_boundaries(); + CHECK_COLROW_BOUNDARIES; DLOG("new_col = %d, new_row = %d\n", new_col, new_row); if (t_ws->table[new_col][new_row]->currently_focused == NULL) { @@ -184,9 +186,26 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t continue; new_col = cols; + DLOG("Fixed it to new col %d\n", new_col); + break; + } + } + + if (t_ws->table[new_col][new_row]->currently_focused == NULL) { + DLOG("Cell still empty, checking for full cols above spanned width...\n"); + DLOG("new_col = %d\n", new_col); + DLOG("colspan = %d\n", container->colspan); + for (int cols = new_col; + cols < container->col + container->colspan; + cols += t_ws->table[cols][new_row]->colspan) { + DLOG("candidate: new_row = %d, cols = %d\n", new_row, cols); + if (t_ws->table[cols][new_row]->currently_focused == NULL) + continue; + + new_col = cols; + DLOG("Fixed it to new col %d\n", new_col); break; } - DLOG("Fixed it to new col %d\n", new_col); } } else if (direction == D_LEFT || direction == D_RIGHT) { if (direction == D_RIGHT && cell_exists(t_ws, current_col+1, current_row)) @@ -216,7 +235,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0); } - check_colrow_boundaries(); + CHECK_COLROW_BOUNDARIES; DLOG("new_col = %d, new_row = %d\n", new_col, new_row); if (t_ws->table[new_col][new_row]->currently_focused == NULL) { @@ -226,16 +245,34 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t continue; new_row = rows; + DLOG("Fixed it to new row %d\n", new_row); break; } - DLOG("Fixed it to new row %d\n", new_row); } + + if (t_ws->table[new_col][new_row]->currently_focused == NULL) { + DLOG("Cell still empty, checking for full cols near full spanned height...\n"); + DLOG("new_row = %d\n", new_row); + DLOG("rowspan = %d\n", container->rowspan); + for (int rows = new_row; + rows < container->row + container->rowspan; + rows += t_ws->table[new_col][rows]->rowspan) { + DLOG("candidate: new_col = %d, rows = %d\n", new_col, rows); + if (t_ws->table[new_col][rows]->currently_focused == NULL) + continue; + + new_row = rows; + DLOG("Fixed it to new col %d\n", new_row); + break; + } + } + } else { ELOG("direction unhandled\n"); return; } - check_colrow_boundaries(); + CHECK_COLROW_BOUNDARIES; if (t_ws->table[new_col][new_row]->currently_focused != NULL) set_focus(conn, t_ws->table[new_col][new_row]->currently_focused, true); @@ -563,12 +600,30 @@ static void move_floating_window_to_workspace(xcb_connection_t *conn, Client *cl xcb_flush(conn); } + /* Configure the window above all tiling windows (or below a fullscreen + * window, if any) */ + if (t_ws->fullscreen_client != NULL) { + uint32_t values[] = { t_ws->fullscreen_client->frame, XCB_STACK_MODE_BELOW }; + xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, values); + } else { + Client *last_tiling; + SLIST_FOREACH(last_tiling, &(t_ws->focus_stack), focus_clients) + if (!client_is_floating(last_tiling)) + break; + if (last_tiling != SLIST_END(&(t_ws->focus_stack))) { + uint32_t values[] = { last_tiling->frame, XCB_STACK_MODE_ABOVE }; + xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, values); + } + } + DLOG("done\n"); render_layout(conn); - if (workspace_is_visible(t_ws)) + if (workspace_is_visible(t_ws)) { + client_warp_pointer_into(conn, client); set_focus(conn, client, true); + } } /* @@ -628,7 +683,7 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa } else { if (current_client->fullscreen) { DLOG("Calling client_enter_fullscreen again\n"); - client_enter_fullscreen(conn, current_client); + client_enter_fullscreen(conn, current_client, false); } } @@ -666,6 +721,7 @@ static void jump_to_window(xcb_connection_t *conn, const char *arguments) { } free(classtitle); + workspace_show(conn, client->workspace->num + 1); set_focus(conn, client, true); } @@ -979,12 +1035,16 @@ void parse_command(xcb_connection_t *conn, const char *command) { if (STARTS_WITH(command, "exit")) { LOG("User issued exit-command, exiting without error.\n"); restore_geometry(global_conn); + ipc_shutdown(); exit(EXIT_SUCCESS); } /* Is it a ? */ if (STARTS_WITH(command, "reload")) { load_configuration(conn, NULL, true); + render_layout(conn); + /* Send an IPC event just in case the ws names have changed */ + ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"reload\"}"); return; } @@ -1020,11 +1080,14 @@ void parse_command(xcb_connection_t *conn, const char *command) { return; } - /* Is it 'f' for fullscreen? */ + /* Is it 'f' for fullscreen, or 'fg' for fullscreen_global? */ if (command[0] == 'f') { if (last_focused == NULL) return; - client_toggle_fullscreen(conn, last_focused); + if (command[1] == 'g') + client_toggle_fullscreen_global(conn, last_focused); + else + client_toggle_fullscreen(conn, last_focused); return; } @@ -1036,9 +1099,9 @@ void parse_command(xcb_connection_t *conn, const char *command) { } LOG("Switching mode for current container\n"); int new_mode = MODE_DEFAULT; - if (command[0] == 's') + if (command[0] == 's' && CUR_CELL->mode != MODE_STACK) new_mode = MODE_STACK; - if (command[0] == 'T') + if (command[0] == 'T' && CUR_CELL->mode != MODE_TABBED) new_mode = MODE_TABBED; switch_layout_mode(conn, CUR_CELL, new_mode); return; @@ -1108,6 +1171,9 @@ void parse_command(xcb_connection_t *conn, const char *command) { Workspace *ws = last_focused->workspace; + if (last_focused->fullscreen) + client_leave_fullscreen(conn, last_focused); + toggle_floating_mode(conn, last_focused, false); /* delete all empty columns/rows */ cleanup_table(conn, ws);