SLIST_ENTRY(Colorpixel) colorpixels;
};
+struct Cached_Pixmap {
+ xcb_pixmap_t id;
+
+ /* We’re going to paint on it, so a graphics context will be needed */
+ xcb_gcontext_t gc;
+
+ /* The rect with which the pixmap was created */
+ Rect rect;
+
+ /* The rect of the object to which this pixmap belongs. Necessary to
+ * find out when we need to re-create the pixmap. */
+ Rect *referred_rect;
+
+ xcb_drawable_t referred_drawable;
+};
+
/**
* Contains data for the windows needed to draw the titlebars on in stacking
* mode
*/
struct Stack_Window {
xcb_window_t window;
- xcb_gcontext_t gc;
+ struct Cached_Pixmap pixmap;
Rect rect;
/** Backpointer to the container this stack window is in */
extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
extern xcb_event_handlers_t evenths;
extern int num_screens;
+extern uint8_t root_depth;
extern xcb_atom_t atoms[NUM_ATOMS];
#endif
*/
void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window);
+/**
+ *
+ * Prepares the given Cached_Pixmap for usage (checks whether the size of the
+ * object this pixmap is related to (e.g. a window) has changed and re-creates
+ * the pixmap if so).
+ *
+ */
+void cached_pixmap_prepare(xcb_connection_t *conn, struct Cached_Pixmap *pixmap);
+
#endif
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 */
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);
}
}
int num_screens = 0;
+/* The depth of the root screen (used e.g. for creating new pixmaps later) */
+uint8_t root_depth;
+
/*
* This callback is only a dummy, see xcb_prepare_cb and xcb_check_cb.
* See also man libev(3): "ev_prepare" and "ev_check" - customise your event loop
xcb_property_set_handler(&prophs, WM_NORMAL_HINTS, UINT_MAX, handle_normal_hints, NULL);
/* Get the root window and set the event mask */
- root = xcb_aux_get_screen(conn, screens)->root;
+ xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screens);
+ root = root_screen->root;
+ root_depth = root_screen->root_depth;
uint32_t mask = XCB_CW_EVENT_MASK;
uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
SLIST_REMOVE(&stack_wins, stack_win, Stack_Window, stack_windows);
- xcb_free_gc(conn, stack_win->gc);
+ xcb_free_gc(conn, stack_win->pixmap.gc);
+ xcb_free_pixmap(conn, stack_win->pixmap.id);
xcb_destroy_window(conn, stack_win->window);
stack_win->rect.width = -1;
struct Stack_Window *stack_win = &(container->stack_win);
stack_win->window = create_window(conn, rect, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_CURSOR_LEFT_PTR, mask, values);
- /* Generate a graphics context for the titlebar */
- stack_win->gc = xcb_generate_id(conn);
- xcb_create_gc(conn, stack_win->gc, stack_win->window, 0, 0);
+ /* Initialize the entry for our cached pixmap. It will be
+ * created as soon as it’s needed (see cached_pixmap_prepare). */
+ memset(&(stack_win->pixmap), 0, sizeof(struct Cached_Pixmap));
+ stack_win->pixmap.referred_rect = &stack_win->rect;
+ stack_win->pixmap.referred_drawable = stack_win->window;
stack_win->container = container;
#include <xcb/xcb.h>
#include <xcb/xcb_keysyms.h>
+#include "i3.h"
#include "util.h"
#include "xcb.h"
uint32_t values[] = { XCB_STACK_MODE_ABOVE };
xcb_configure_window(conn, window, XCB_CONFIG_WINDOW_STACK_MODE, values);
}
+
+/*
+ *
+ * Prepares the given Cached_Pixmap for usage (checks whether the size of the
+ * object this pixmap is related to (e.g. a window) has changed and re-creates
+ * the pixmap if so).
+ *
+ */
+void cached_pixmap_prepare(xcb_connection_t *conn, struct Cached_Pixmap *pixmap) {
+ LOG("preparing pixmap\n");
+
+ /* If the Rect did not change, the pixmap does not need to be recreated */
+ if (memcmp(&(pixmap->rect), pixmap->referred_rect, sizeof(Rect)) == 0)
+ return;
+
+ memcpy(&(pixmap->rect), pixmap->referred_rect, sizeof(Rect));
+
+ if (pixmap->id == 0 || pixmap->gc == 0) {
+ LOG("Creating new pixmap...\n");
+ pixmap->id = xcb_generate_id(conn);
+ pixmap->gc = xcb_generate_id(conn);
+ } else {
+ LOG("Re-creating this pixmap...\n");
+ xcb_free_gc(conn, pixmap->gc);
+ xcb_free_pixmap(conn, pixmap->id);
+ }
+
+ xcb_create_pixmap(conn, root_depth, pixmap->id,
+ pixmap->referred_drawable, pixmap->rect.width, pixmap->rect.height);
+
+ xcb_create_gc(conn, pixmap->gc, pixmap->id, 0, 0);
+}