X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Flayout.c;h=c0471173bd0e376d251001f110f830e13298cb8c;hb=47a798ac4a5b7ac22dcd101220804032db44b7c1;hp=952f3d60453cefdc2cd721649d90f377eceaaec4;hpb=8e19f8dabfea60fcf34a6f5e5966278747121948;p=i3%2Fi3 diff --git a/src/layout.c b/src/layout.c index 952f3d60..c0471173 100644 --- a/src/layout.c +++ b/src/layout.c @@ -24,6 +24,8 @@ #include "util.h" #include "xinerama.h" #include "layout.h" +#include "client.h" +#include "floating.h" /* * Updates *destination with new_value and returns true if it was changed or false @@ -101,19 +103,27 @@ void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t draw i3Font *font = load_font(conn, config.font); int decoration_height = font->height + 2 + 2; struct Colortriple *color; + Client *last_focused; /* Clients without a container (docks) won’t get decorated */ if (client->dock) return; LOG("redecorating child %08x\n", client->child); - if (client->floating >= FLOATING_AUTO_ON || client->container->currently_focused == client) { - /* Distinguish if the window is currently focused… */ - if (client->floating >= FLOATING_AUTO_ON || CUR_CELL->currently_focused == client) + last_focused = SLIST_FIRST(&(client->workspace->focus_stack)); + if (client_is_floating(client)) { + if (last_focused == client) color = &(config.client.focused); - /* …or if it is the focused window in a not focused container */ - else color = &(config.client.focused_inactive); - } else color = &(config.client.unfocused); + else color = &(config.client.unfocused); + } else { + if (client->container->currently_focused == client) { + /* Distinguish if the window is currently focused… */ + if (last_focused == client) + color = &(config.client.focused); + /* …or if it is the focused window in a not focused container */ + else color = &(config.client.focused_inactive); + } else color = &(config.client.unfocused); + } /* Our plan is the following: - Draw a rect around the whole client in color->background @@ -143,10 +153,12 @@ void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t draw xcb_poly_fill_rectangle(conn, client->frame, client->titlegc, 1, &crect); } - /* Draw the lines */ - xcb_draw_line(conn, drawable, gc, color->border, 0, offset, client->rect.width, offset); - xcb_draw_line(conn, drawable, gc, color->border, 2, offset + font->height + 3, - client->rect.width - 3, offset + font->height + 3); + if (client->titlebar_position != TITLEBAR_OFF) { + /* Draw the lines */ + xcb_draw_line(conn, drawable, gc, color->border, 0, offset, client->rect.width, offset); + xcb_draw_line(conn, drawable, gc, color->border, 2, offset + font->height + 3, + client->rect.width - 3, offset + font->height + 3); + } /* If the client has a title, we draw it */ if (client->name != NULL) { @@ -172,10 +184,29 @@ void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t draw * */ void reposition_client(xcb_connection_t *conn, Client *client) { + i3Screen *screen; + LOG("frame 0x%08x needs to be pushed to %dx%d\n", client->frame, client->rect.x, client->rect.y); /* Note: We can use a pointer to client->x like an array of uint32_ts because it is followed by client->y by definition */ xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, &(client->rect.x)); + + if (!client_is_floating(client)) + return; + + /* If the client is floating, we need to check if we moved it to a different workspace */ + if (client->workspace->screen == (screen = get_screen_containing(client->rect.x, client->rect.y))) + return; + + if (screen == NULL) { + LOG("Boundary checking disabled, no screen found for (%d, %d)\n", client->rect.x, client->rect.y); + return; + } + + 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, &workspaces[screen->current_workspace]); + LOG("fixed that\n"); } /* @@ -206,11 +237,16 @@ void resize_client(xcb_connection_t *conn, Client *client) { rect->height = client->rect.height - 2; break; default: - if (client->titlebar_position == TITLEBAR_OFF) { + if (client->titlebar_position == TITLEBAR_OFF && client->borderless) { rect->x = 0; rect->y = 0; rect->width = client->rect.width; rect->height = client->rect.height; + } else if (client->titlebar_position == TITLEBAR_OFF && !client->borderless) { + rect->x = 1; + rect->y = 1; + rect->width = client->rect.width - 1 - 1; + rect->height = client->rect.height - 1 - 1; } else { rect->x = 2; rect->y = font->height + 2 + 2; @@ -261,9 +297,6 @@ void render_container(xcb_connection_t *conn, Container *container) { Client *client; int num_clients = 0, current_client = 0; - if (container->currently_focused == NULL) - return; - CIRCLEQ_FOREACH(client, &(container->clients), clients) num_clients++; @@ -301,7 +334,7 @@ void render_container(xcb_connection_t *conn, Container *container) { /* Check if we need to remap our stack title window, it gets unmapped when the container is empty in src/handlers.c:unmap_notify() */ - if (stack_win->rect.height == 0) + if (stack_win->rect.height == 0 && num_clients > 0) xcb_map_window(conn, stack_win->window); /* Check if we need to reconfigure our stack title window */ @@ -341,6 +374,9 @@ void render_container(xcb_connection_t *conn, Container *container) { xcb_configure_window(conn, stack_win->window, mask, values); } + /* Prepare the pixmap for usage */ + cached_pixmap_prepare(conn, &(stack_win->pixmap)); + /* Render the decorations of all clients */ CIRCLEQ_FOREACH(client, &(container->clients), clients) { /* If the client is in fullscreen mode, it does not get reconfigured */ @@ -363,9 +399,12 @@ void render_container(xcb_connection_t *conn, Container *container) { client->force_reconfigure = false; - decorate_window(conn, client, stack_win->window, stack_win->gc, + decorate_window(conn, client, stack_win->pixmap.id, stack_win->pixmap.gc, current_client++ * decoration_height); } + + xcb_copy_area(conn, stack_win->pixmap.id, stack_win->window, stack_win->pixmap.gc, + 0, 0, 0, 0, stack_win->rect.width, stack_win->rect.height); } } @@ -374,7 +413,7 @@ static void render_bars(xcb_connection_t *conn, Workspace *r_ws, int width, int SLIST_FOREACH(client, &(r_ws->screen->dock_clients), dock_clients) { LOG("client is at %d, should be at %d\n", client->rect.y, *height); if (client->force_reconfigure | - update_if_necessary(&(client->rect.x), 0) | + update_if_necessary(&(client->rect.x), r_ws->rect.x) | update_if_necessary(&(client->rect.y), *height)) reposition_client(conn, client); @@ -394,7 +433,6 @@ static void render_internal_bar(xcb_connection_t *conn, Workspace *r_ws, int wid i3Font *font = load_font(conn, config.font); i3Screen *screen = r_ws->screen; enum { SET_NORMAL = 0, SET_FOCUSED = 1 }; - char label[3]; /* Fill the whole bar in black */ xcb_change_gc_single(conn, screen->bargc, XCB_GC_FOREGROUND, get_colorpixel(conn, "#000000")); @@ -411,18 +449,28 @@ static void render_internal_bar(xcb_connection_t *conn, Workspace *r_ws, int wid struct Colortriple *color = (screen->current_workspace == c ? &(config.bar.focused) : &(config.bar.unfocused)); + Workspace *ws = &workspaces[c]; + /* Draw the outer rect */ xcb_draw_rect(conn, screen->bar, screen->bargc, color->border, - drawn * height, 1, height - 2, height - 2); + drawn, /* x */ + 1, /* y */ + ws->text_width + 5 + 5, /* width = text width + 5 px left + 5px right */ + height - 2 /* height = max. height - 1 px upper and 1 px bottom border */); + + /* Draw the background of this rect */ xcb_draw_rect(conn, screen->bar, screen->bargc, color->background, - drawn * height + 1, 2, height - 4, height - 4); + drawn + 1, + 2, + ws->text_width + 4 + 4, + height - 4); - snprintf(label, sizeof(label), "%d", c+1); xcb_change_gc_single(conn, screen->bargc, XCB_GC_FOREGROUND, color->text); xcb_change_gc_single(conn, screen->bargc, XCB_GC_BACKGROUND, color->background); - xcb_image_text_8(conn, strlen(label), screen->bar, screen->bargc, drawn * height + 5 /* X */, - font->height + 1 /* Y = baseline of font */, label); - drawn++; + xcb_image_text_16(conn, ws->name_len, screen->bar, screen->bargc, drawn + 5 /* X */, + font->height + 1 /* Y = baseline of font */, + (xcb_char2b_t*)ws->name); + drawn += ws->text_width + 12; } LOG("done rendering internal\n");