#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 */
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);
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) {
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))
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) {
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);
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);
+ }
}
/*
} 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);
}
}
}
free(classtitle);
+ workspace_show(conn, client->workspace->num + 1);
set_focus(conn, client, true);
}
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 <reload>? */
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;
}
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;
}
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);