Refactor workspaces to be stored in a TAILQ instead of an array

This fixes many problems we were having with a dynamically growing
array because of the realloc (pointers inside the area which was
allocated were no longer valid as soon as the realloc moved the
memory to another address).

Again, this is a rather big change, so expect problems and enable
core-dumps.
This commit is contained in:
Michael Stapelberg 2009-09-29 19:45:41 +02:00
parent 5a77081c55
commit 2b70e05ee9
15 changed files with 142 additions and 172 deletions

View File

@ -232,6 +232,8 @@ struct Workspace {
* opened, for example) have the same size as always */
float *width_factor;
float *height_factor;
TAILQ_ENTRY(Workspace) workspaces;
};
/**
@ -492,7 +494,7 @@ struct Screen {
int num;
/** Current workspace selected on this virtual screen */
int current_workspace;
Workspace *current_workspace;
/** x, y, width, height */
Rect rect;

View File

@ -21,8 +21,8 @@
#define CUR_CELL (CUR_TABLE[current_col][current_row])
extern Workspace *c_ws;
extern Workspace *workspaces;
extern int num_workspaces;
extern TAILQ_HEAD(workspaces_head, Workspace) *workspaces;
//extern int num_workspaces;
extern int current_col;
extern int current_row;

View File

@ -112,7 +112,7 @@ void parse_file(const char *f) {
/* Then, allocate a new buffer and copy the file over to the new one,
* but replace occurences of our variables */
char *walk = buf, *destwalk;
char *new = smalloc((stbuf.st_size + extra_bytes) * sizeof(char));
char *new = smalloc((stbuf.st_size + extra_bytes + 1) * sizeof(char));
destwalk = new;
while (walk < (buf + stbuf.st_size)) {
/* Find the next variable */
@ -335,11 +335,12 @@ new_container:
* Thus, the user very likely awaits the default container mode
* to trigger in this case, regardless of where it is inside
* his configuration file. */
for (int c = 0; c < num_workspaces; c++) {
if (workspaces[c].table == NULL)
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->table == NULL)
continue;
switch_layout_mode(global_conn,
workspaces[c].table[0][0],
ws->table[0][0],
config.container_mode);
}
}
@ -350,10 +351,11 @@ new_container:
config.container_stack_limit_value = $<number>7;
/* See the comment above */
for (int c = 0; c < num_workspaces; c++) {
if (workspaces[c].table == NULL)
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->table == NULL)
continue;
Container *con = workspaces[c].table[0][0];
Container *con = ws->table[0][0];
con->stack_limit = config.container_stack_limit;
con->stack_limit_value = config.container_stack_limit_value;
}

View File

@ -128,29 +128,40 @@ static bool button_press_bar(xcb_connection_t *conn, xcb_button_press_event_t *e
/* Check if the button was one of button4 or button5 (scroll up / scroll down) */
if (event->detail == XCB_BUTTON_INDEX_4 || event->detail == XCB_BUTTON_INDEX_5) {
int add = (event->detail == XCB_BUTTON_INDEX_4 ? -1 : 1);
for (int i = c_ws->num + add; (i >= 0) && (i < num_workspaces); i += add)
if (workspaces[i].screen == screen) {
workspace_show(conn, i+1);
return true;
Workspace *ws = c_ws;
if (event->detail == XCB_BUTTON_INDEX_5) {
while ((ws = TAILQ_NEXT(ws, workspaces)) != TAILQ_END(workspaces_head)) {
if (ws->screen == screen) {
workspace_show(conn, ws->num + 1);
return true;
}
}
} else {
while ((ws = TAILQ_PREV(ws, workspaces_head, workspaces)) != TAILQ_END(workspaces)) {
if (ws->screen == screen) {
workspace_show(conn, ws->num + 1);
return true;
}
}
}
return true;
}
int drawn = 0;
/* Because workspaces can be on different screens, we need to loop
through all of them and decide to count it based on its ->screen */
for (int i = 0; i < num_workspaces; i++) {
if (workspaces[i].screen != screen)
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->screen != screen)
continue;
LOG("Checking if click was on workspace %d with drawn = %d, tw = %d\n",
i, drawn, workspaces[i].text_width);
ws->num, drawn, ws->text_width);
if (event->event_x > (drawn + 1) &&
event->event_x <= (drawn + 1 + workspaces[i].text_width + 5 + 5)) {
workspace_show(conn, i+1);
event->event_x <= (drawn + 1 + ws->text_width + 5 + 5)) {
workspace_show(conn, ws->num + 1);
return true;
}
drawn += workspaces[i].text_width + 5 + 5 + 2;
drawn += ws->text_width + 5 + 5 + 2;
}
return true;
}

View File

@ -332,8 +332,9 @@ void client_mark(xcb_connection_t *conn, Client *client, const char *mark) {
/* Make sure no other client has this mark set */
Client *current;
for (int c = 0; c < 10; c++)
SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) {
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces)
SLIST_FOREACH(current, &(ws->focus_stack), focus_clients) {
if (current == client ||
current->mark == NULL ||
strcmp(current->mark, mark) != 0)

View File

@ -63,8 +63,9 @@ static void jump_to_mark(xcb_connection_t *conn, const char *mark) {
Client *current;
LOG("Jumping to \"%s\"\n", mark);
for (int c = 0; c < num_workspaces; c++)
SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) {
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces)
SLIST_FOREACH(current, &(ws->focus_stack), focus_clients) {
if (current->mark == NULL || strcmp(current->mark, mark) != 0)
continue;
@ -130,7 +131,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
}
LOG("Switching to ws %d\n", target->current_workspace + 1);
workspace_show(conn, target->current_workspace + 1);
workspace_show(conn, target->current_workspace->num + 1);
return;
}
@ -165,7 +166,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
/* No screen found? Then wrap */
screen = get_screen_most((direction == D_UP ? D_DOWN : D_UP), container->workspace->screen);
}
t_ws = workspace_get(screen->current_workspace);
t_ws = screen->current_workspace;
new_row = (direction == D_UP ? (t_ws->rows - 1) : 0);
}
@ -207,7 +208,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
LOG("Wrapping screen around horizontally\n");
screen = get_screen_most((direction == D_LEFT ? D_RIGHT : D_LEFT), container->workspace->screen);
}
t_ws = workspace_get(screen->current_workspace);
t_ws = screen->current_workspace;
new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0);
}
@ -784,31 +785,25 @@ static char **append_argument(char **original, char *argument) {
*
*/
static void next_previous_workspace(xcb_connection_t *conn, int direction) {
Workspace *t_ws;
int i;
Workspace *ws = c_ws;
if (direction == 'n') {
/* If we are on the last workspace, we cannot go any further */
if (c_ws->num == (num_workspaces-1))
return;
while ((ws = TAILQ_NEXT(ws, workspaces)) != TAILQ_END(workspaces_head)) {
if (ws->screen == NULL)
continue;
for (i = c_ws->num + 1; i < num_workspaces; i++) {
t_ws = &(workspaces[i]);
if (t_ws->screen != NULL)
break;
workspace_show(conn, ws->num + 1);
return;
}
} else if (direction == 'p') {
if (c_ws->num == 0)
while ((ws = TAILQ_PREV(ws, workspaces_head, workspaces)) != TAILQ_END(workspaces)) {
if (ws->screen == NULL)
continue;
workspace_show(conn, ws->num + 1);
return;
for (i = c_ws->num - 1; i >= 0 ; i--) {
t_ws = &(workspaces[i]);
if (t_ws->screen != NULL)
break;
}
}
if (t_ws->screen != NULL)
workspace_show(conn, i+1);
}
static void parse_resize_command(xcb_connection_t *conn, Client *last_focused, const char *command) {

View File

@ -183,6 +183,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
while (!TAILQ_EMPTY(bindings)) {
bind = TAILQ_FIRST(bindings);
TAILQ_REMOVE(bindings, bind, bindings);
FREE(bind->translated_to);
FREE(bind->command);
FREE(bind);
}
@ -481,7 +482,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
LOG("setting name to \"%s\"\n", name);
if (*name != '\0')
workspace_set_name(&(workspaces[ws_num - 1]), name);
workspace_set_name(workspace_get(ws_num - 1), name);
free(ws_str);
continue;
}
@ -590,8 +591,8 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
REQUIRED_OPTION(font);
/* Set an empty name for every workspace which got no name */
for (int i = 0; i < num_workspaces; i++) {
Workspace *ws = &(workspaces[i]);
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->name != NULL) {
/* If the font was not specified when the workspace name
* was loaded, we need to predict the text width now */
@ -601,7 +602,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
continue;
}
workspace_set_name(&(workspaces[i]), NULL);
workspace_set_name(ws, NULL);
}
return;

View File

@ -170,7 +170,7 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) {
c_ws->current_row = current_row;
c_ws->current_col = current_col;
c_ws = &workspaces[screen->current_workspace];
c_ws = screen->current_workspace;
current_row = c_ws->current_row;
current_col = c_ws->current_col;
LOG("We're now on virtual screen number %d\n", screen->num);
@ -486,7 +486,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
/* If this workspace is currently active, we dont delete it */
i3Screen *screen;
TAILQ_FOREACH(screen, virtual_screens, screens)
if (screen->current_workspace == client->workspace->num) {
if (screen->current_workspace == client->workspace) {
workspace_active = true;
workspace_empty = false;
break;
@ -908,7 +908,7 @@ int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t
* the workspace bar */
if (!workspace_is_visible(client->workspace)) {
i3Screen *screen = client->workspace->screen;
render_workspace(conn, screen, &(workspaces[screen->current_workspace]));
render_workspace(conn, screen, screen->current_workspace);
xcb_flush(conn);
}

View File

@ -238,7 +238,7 @@ void reposition_client(xcb_connection_t *conn, Client *client) {
LOG("Client is on workspace %p with screen %p\n", client->workspace, client->workspace->screen);
LOG("but screen at %d, %d is %p\n", client->rect.x, client->rect.y, screen);
floating_assign_to_workspace(client, workspace_get(screen->current_workspace));
floating_assign_to_workspace(client, screen->current_workspace);
}
/*
@ -586,14 +586,14 @@ static void render_internal_bar(xcb_connection_t *conn, Workspace *r_ws, int wid
xcb_change_gc_single(conn, screen->bargc, XCB_GC_FONT, font->id);
int drawn = 0;
for (int c = 0; c < num_workspaces; c++) {
if (workspaces[c].screen != screen)
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->screen != screen)
continue;
struct Colortriple *color;
Workspace *ws = &workspaces[c];
if (screen->current_workspace == c)
if (screen->current_workspace == ws)
color = &(config.bar.focused);
else if (ws->urgent)
color = &(config.bar.urgent);
@ -742,7 +742,8 @@ void render_layout(xcb_connection_t *conn) {
return;
TAILQ_FOREACH(screen, virtual_screens, screens)
render_workspace(conn, screen, &(workspaces[screen->current_workspace]));
if (screen->current_workspace != NULL)
render_workspace(conn, screen, screen->current_workspace);
xcb_flush(conn);
}

View File

@ -211,8 +211,8 @@ int main(int argc, char *argv[], char *env[]) {
* connection and a loaded configuration (default mode for new
* containers may be stacking, which requires a new window to be
* created), it had to be delayed. */
expand_table_cols(&(workspaces[0]));
expand_table_rows(&(workspaces[0]));
expand_table_cols(TAILQ_FIRST(workspaces));
expand_table_rows(TAILQ_FIRST(workspaces));
/* Place requests for the atoms we need as soon as possible */
#define REQUEST_ATOM(name) atom_cookies[name] = xcb_intern_atom(conn, 0, strlen(#name), #name);
@ -456,7 +456,7 @@ int main(int argc, char *argv[], char *env[]) {
}
LOG("Starting on %d\n", screen->current_workspace);
c_ws = &workspaces[screen->current_workspace];
c_ws = screen->current_workspace;
manage_existing_windows(conn, &prophs, root);

View File

@ -329,7 +329,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
LOG("Assignment \"%s\" matches, so putting it on workspace %d\n",
assign->windowclass_title, assign->workspace);
if (c_ws->screen->current_workspace == (assign->workspace-1)) {
if (c_ws->screen->current_workspace->num == (assign->workspace-1)) {
LOG("We are already there, no need to do anything\n");
break;
}

View File

@ -26,10 +26,11 @@
#include "i3.h"
#include "layout.h"
#include "config.h"
#include "workspace.h"
int current_workspace = 0;
int num_workspaces = 1;
Workspace *workspaces;
struct workspaces_head *workspaces;
/* Convenience pointer to the current workspace */
Workspace *c_ws;
int current_col = 0;
@ -40,12 +41,13 @@ int current_row = 0;
*
*/
void init_table() {
workspaces = scalloc(sizeof(Workspace));
c_ws = workspaces;
workspaces = scalloc(sizeof(struct workspaces_head));
TAILQ_INIT(workspaces);
workspaces[0].screen = NULL;
workspaces[0].num = 0;
TAILQ_INIT(&(workspaces[0].floating_clients));
c_ws = scalloc(sizeof(Workspace));
workspace_set_name(c_ws, NULL);
TAILQ_INIT(&(c_ws->floating_clients));
TAILQ_INSERT_TAIL(workspaces, c_ws, workspaces);
}
static void new_container(Workspace *workspace, Container **container, int col, int row) {

View File

@ -458,12 +458,13 @@ Client *get_matching_client(xcb_connection_t *conn, const char *window_classtitl
}
LOG("Getting clients for class \"%s\" / title \"%s\"\n", to_class, to_title);
for (int workspace = 0; workspace < num_workspaces; workspace++) {
if (workspaces[workspace].screen == NULL)
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->screen == NULL)
continue;
Client *client;
SLIST_FOREACH(client, &(workspaces[workspace].focus_stack), focus_clients) {
SLIST_FOREACH(client, &(ws->focus_stack), focus_clients) {
LOG("Checking client with class=%s, name=%s\n", client->window_class, client->name);
if (!client_matches_class_name(client, to_class, to_title, to_title_ucs, to_title_ucs_len))
continue;

View File

@ -34,80 +34,31 @@
*
*/
Workspace *workspace_get(int number) {
if (number > (num_workspaces-1)) {
int old_num_workspaces = num_workspaces;
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces)
if (ws->num == number)
return ws;
/* Convert all container->workspace and client->workspace
* pointers to numbers representing their workspace. Necessary
* because the realloc() may make all the pointers invalid, so
* we need to preserve them this way and restore them later.
*
* To distinguish between the first workspace and a NULL
* pointer, we store <workspace number> + 1. */
for (int c = 0; c < num_workspaces; c++) {
FOR_TABLE(&(workspaces[c])) {
Container *con = workspaces[c].table[cols][rows];
if (con->workspace != NULL) {
LOG("Handling con %p with pointer %p (num %d)\n", con, con->workspace, con->workspace->num);
con->workspace = (Workspace*)(con->workspace->num + 1);
}
}
Client *current;
SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) {
if (current->workspace == NULL)
continue;
LOG("Handling client %p with pointer %p (num %d)\n", current, current->workspace, current->workspace->num);
current->workspace = (Workspace*)(current->workspace->num + 1);
}
}
/* If we are still there, we could not find the requested workspace. */
int last_ws = TAILQ_LAST(workspaces, workspaces_head)->num;
/* preserve c_ws */
c_ws = (Workspace*)(c_ws->num);
LOG("We need to initialize that one, last ws = %d\n", last_ws);
LOG("We need to initialize that one\n");
num_workspaces = number+1;
workspaces = realloc(workspaces, num_workspaces * sizeof(Workspace));
/* Zero out the new workspaces so that we have sane default values */
for (int c = old_num_workspaces; c < num_workspaces; c++)
memset(&workspaces[c], 0, sizeof(Workspace));
for (int c = last_ws; c < number; c++) {
LOG("Creating new ws\n");
/* Immediately after the realloc(), we restore the pointers.
* They may be used when initializing the new workspaces, for
* example when the user configures containers to be stacking
* by default, thus requiring re-rendering the layout. */
c_ws = workspace_get((int)c_ws);
ws = scalloc(sizeof(Workspace));
ws->num = number;
TAILQ_INIT(&(ws->floating_clients));
expand_table_cols(ws);
expand_table_rows(ws);
workspace_set_name(ws, NULL);
for (int c = 0; c < old_num_workspaces; c++) {
FOR_TABLE(&(workspaces[c])) {
Container *con = workspaces[c].table[cols][rows];
if (con->workspace != NULL) {
LOG("Handling con %p with (num %d)\n", con, con->workspace);
con->workspace = workspace_get((int)con->workspace - 1);
}
}
Client *current;
SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) {
if (current->workspace == NULL)
continue;
LOG("Handling client %p with (num %d)\n", current, current->workspace);
current->workspace = workspace_get((int)current->workspace - 1);
}
}
/* Initialize the new workspaces */
for (int c = old_num_workspaces; c < num_workspaces; c++) {
memset(&workspaces[c], 0, sizeof(Workspace));
workspaces[c].num = c;
TAILQ_INIT(&(workspaces[c].floating_clients));
expand_table_cols(&(workspaces[c]));
expand_table_rows(&(workspaces[c]));
workspace_set_name(&(workspaces[c]), NULL);
}
LOG("done\n");
TAILQ_INSERT_TAIL(workspaces, ws, workspaces);
}
LOG("done\n");
return &(workspaces[number]);
return ws;
}
/*
@ -145,7 +96,7 @@ void workspace_set_name(Workspace *ws, const char *name) {
*
*/
bool workspace_is_visible(Workspace *ws) {
return (ws->screen->current_workspace == ws->num);
return (ws->screen->current_workspace == ws);
}
/*
@ -174,7 +125,7 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
/* Store the old client */
Client *old_client = CUR_CELL->currently_focused;
c_ws = workspace_get(t_ws->screen->current_workspace);
c_ws = t_ws->screen->current_workspace;
current_col = c_ws->current_col;
current_row = c_ws->current_row;
if (CUR_CELL->currently_focused != NULL)
@ -192,7 +143,7 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
}
/* Check if we need to change something or if were already there */
if (c_ws->screen->current_workspace == (workspace-1)) {
if (c_ws->screen->current_workspace->num == (workspace-1)) {
Client *last_focused = SLIST_FIRST(&(c_ws->focus_stack));
if (last_focused != SLIST_END(&(c_ws->focus_stack)))
set_focus(conn, last_focused, true);
@ -204,9 +155,8 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
return;
}
t_ws->screen->current_workspace = workspace-1;
Workspace *old_workspace = c_ws;
c_ws = workspace_get(workspace-1);
c_ws = t_ws->screen->current_workspace = workspace_get(workspace-1);
/* Unmap all clients of the old workspace */
workspace_unmap_clients(conn, old_workspace);
@ -325,8 +275,8 @@ void workspace_initialize(Workspace *ws, i3Screen *screen) {
Workspace *get_first_workspace_for_screen(struct screens_head *slist, i3Screen *screen) {
Workspace *result = NULL;
for (int c = 0; c < num_workspaces; c++) {
Workspace *ws = workspace_get(c);
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->preferred_screen == NULL ||
!screens_are_equal(get_screen_from_preference(slist, ws->preferred_screen), screen))
continue;
@ -337,11 +287,12 @@ Workspace *get_first_workspace_for_screen(struct screens_head *slist, i3Screen *
if (result == NULL) {
/* No assignment found, returning first unused workspace */
for (int c = 0; c < num_workspaces; c++) {
if (workspaces[c].screen != NULL)
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->screen != NULL)
continue;
result = workspace_get(c);
result = ws;
break;
}
}
@ -349,7 +300,11 @@ Workspace *get_first_workspace_for_screen(struct screens_head *slist, i3Screen *
if (result == NULL) {
LOG("No existing free workspace found to assign, creating a new one\n");
result = workspace_get(num_workspaces);
Workspace *ws;
int last_ws = 0;
TAILQ_FOREACH(ws, workspaces, workspaces)
last_ws = ws->num;
result = workspace_get(last_ws + 1);
}
workspace_initialize(result, screen);

View File

@ -133,7 +133,7 @@ static void initialize_screen(xcb_connection_t *conn, i3Screen *screen, Workspac
i3Font *font = load_font(conn, config.font);
workspace->screen = screen;
screen->current_workspace = workspace->num;
screen->current_workspace = workspace;
/* Create a bar for each screen */
Rect bar_rect = {screen->rect.x,
@ -298,12 +298,13 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
int screen_count = 0;
/* Mark each workspace which currently is assigned to a screen, so we
* can garbage-collect afterwards */
for (int c = 0; c < num_workspaces; c++)
workspaces[c].reassigned = (workspaces[c].screen == NULL);
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces)
ws->reassigned = (ws->screen == NULL);
TAILQ_FOREACH(screen, new_screens, screens) {
screen->num = screen_count;
screen->current_workspace = -1;
screen->current_workspace = NULL;
TAILQ_FOREACH(old_screen, virtual_screens, screens) {
if (old_screen->num != screen_count)
@ -334,8 +335,8 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
screen->dock_clients = old_screen->dock_clients;
/* Update the dimensions */
for (int c = 0; c < num_workspaces; c++) {
Workspace *ws = &(workspaces[c]);
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->screen != old_screen)
continue;
@ -347,7 +348,7 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
break;
}
if (screen->current_workspace == -1) {
if (screen->current_workspace == NULL) {
/* Find the first unused workspace, preferring the ones
* which are assigned to this screen and initialize
* the screen with it. */
@ -364,38 +365,36 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
}
/* Check for workspaces which are out of bounds */
for (int c = 0; c < num_workspaces; c++) {
if (workspaces[c].reassigned)
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->reassigned)
continue;
/* f_ws is a shortcut to the workspace to fix */
Workspace *f_ws = &(workspaces[c]);
Client *client;
LOG("Closing bar window (%p)\n", f_ws->screen->bar);
xcb_destroy_window(conn, f_ws->screen->bar);
LOG("Closing bar window (%p)\n", ws->screen->bar);
xcb_destroy_window(conn, ws->screen->bar);
LOG("Workspace %d's screen out of bounds, assigning to first screen\n", c+1);
f_ws->screen = first;
memcpy(&(f_ws->rect), &(first->rect), sizeof(Rect));
LOG("Workspace %d's screen out of bounds, assigning to first screen\n", ws->num + 1);
ws->screen = first;
memcpy(&(ws->rect), &(first->rect), sizeof(Rect));
/* Force reconfiguration for each client on that workspace */
FOR_TABLE(f_ws)
CIRCLEQ_FOREACH(client, &(f_ws->table[cols][rows]->clients), clients)
FOR_TABLE(ws)
CIRCLEQ_FOREACH(client, &(ws->table[cols][rows]->clients), clients)
client->force_reconfigure = true;
/* Render the workspace to reconfigure the clients. However, they will be visible now, so… */
render_workspace(conn, first, f_ws);
render_workspace(conn, first, ws);
/* …unless we want to see them at the moment, we should hide that workspace */
if (workspace_is_visible(f_ws))
if (workspace_is_visible(ws))
continue;
workspace_unmap_clients(conn, f_ws);
workspace_unmap_clients(conn, ws);
if (c_ws == f_ws) {
if (c_ws == ws) {
LOG("Need to adjust c_ws...\n");
c_ws = &(workspaces[first->current_workspace]);
c_ws = first->current_workspace;
}
}
xcb_flush(conn);