Go to the documentation of this file.
14 #ifdef I3_ASAN_ENABLED
15 #include <sanitizer/lsan_interface.h>
18 #define TEXT_PADDING logical_px(2)
38 static xcb_connection_t *restore_conn;
40 static struct ev_io *xcb_watcher;
46 static void restore_xcb_got_event(EV_P_
struct ev_io *w,
int revents) {
50 xcb_generic_event_t *event;
52 if (xcb_connection_has_error(restore_conn)) {
53 DLOG(
"restore X11 connection has an error, reconnecting\n");
58 while ((event = xcb_poll_for_event(restore_conn)) != NULL) {
59 if (event->response_type == 0) {
60 xcb_generic_error_t *error = (xcb_generic_error_t *)event;
61 DLOG(
"X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
62 error->sequence, error->error_code);
68 int type = (
event->response_type & 0x7F);
75 xcb_flush(restore_conn);
86 if (restore_conn != NULL) {
103 xcb_disconnect(restore_conn);
109 restore_conn = xcb_connect(NULL, &screen);
110 if (restore_conn == NULL || xcb_connection_has_error(restore_conn)) {
111 if (restore_conn != NULL) {
112 xcb_disconnect(restore_conn);
114 #ifdef I3_ASAN_ENABLED
115 __lsan_do_leak_check();
117 errx(EXIT_FAILURE,
"Cannot open display");
120 xcb_watcher =
scalloc(1,
sizeof(
struct ev_io));
123 ev_io_init(xcb_watcher, restore_xcb_got_event, xcb_get_file_descriptor(restore_conn), EV_READ);
137 xcb_aux_sync(restore_conn);
142 char *serialized = NULL;
144 #define APPEND_REGEX(re_name) \
146 if (swallows->re_name != NULL) { \
147 sasprintf(&serialized, "%s%s" #re_name "=\"%s\"", (serialized ? serialized : "["), (serialized ? " " : ""), swallows->re_name->pattern); \
157 if (serialized == NULL) {
158 DLOG(
"This swallows specification is not serializable?!\n");
162 sasprintf(&serialized,
"%s]", serialized);
163 DLOG(
"con %p (placeholder 0x%08x) line %d: %s\n",
state->con,
state->window, n, serialized);
178 int x = (
state->rect.width / 2) - (text_width / 2);
182 xcb_aux_sync(restore_conn);
189 con->
type == CT_CON) {
193 XCB_COPY_FROM_PARENT,
194 XCB_COPY_FROM_PARENT,
195 XCB_WINDOW_CLASS_INPUT_OUTPUT,
198 XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
200 config.client[QUBE_DOM0].placeholder.background.colorpixel,
201 XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
204 xcb_icccm_wm_hints_t hints;
205 xcb_icccm_wm_hints_set_none(&hints);
206 xcb_icccm_wm_hints_set_input(&hints, 0);
207 xcb_icccm_set_wm_hints(restore_conn, placeholder, &hints);
211 if (con->
name != NULL)
212 xcb_change_property(restore_conn, XCB_PROP_MODE_REPLACE, placeholder,
213 A__NET_WM_NAME, A_UTF8_STRING, 8, strlen(con->
name), con->
name);
214 DLOG(
"Created placeholder window 0x%08x for leaf container %p / %s\n",
215 placeholder, con, con->
name);
218 state->window = placeholder;
229 temp_id->
dock = M_DONTCHECK;
230 temp_id->
id = placeholder;
238 TAILQ_FOREACH (child, &(con->floating_head), floating_windows) {
255 TAILQ_FOREACH (child, &(parent->floating_head), floating_windows) {
259 xcb_flush(restore_conn);
272 if (
state->window != placeholder)
275 xcb_destroy_window(restore_conn,
state->window);
279 DLOG(
"placeholder window 0x%08x destroyed.\n", placeholder);
283 DLOG(
"0x%08x is not a placeholder window, ignoring.\n", placeholder);
290 if (
state->window != event->window)
293 DLOG(
"refreshing window 0x%08x contents (con %p)\n",
state->window,
state->con);
300 ELOG(
"Received ExposeEvent for unknown window 0x%08x\n", event->window);
312 if (
state->window != event->window)
315 DLOG(
"ConfigureNotify: window 0x%08x has now width=%d, height=%d (con %p)\n",
316 state->window, event->width, event->height,
state->con);
318 state->rect.width =
event->width;
319 state->rect.height =
event->height;
328 ELOG(
"Received ConfigureNotify for unknown window 0x%08x\n", event->window);
334 if (((xcb_expose_event_t *)event)->count == 0) {
339 case XCB_CONFIGURE_NOTIFY:
343 DLOG(
"Received unhandled X11 event of type %d\n", type);
struct _i3String i3String
Opaque data structure for storing strings.
#define TAILQ_FIRST(head)
i3String * i3string_from_utf8(const char *from_utf8)
Build an i3String from an UTF-8 encoded string.
void match_init(Match *match)
Initializes the Match data structure.
bool con_is_leaf(Con *con)
Returns true when this node is a leaf node (has no children)
Stores a rectangle, for example the size of a window, the child window etc.
void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface)
Destroys the surface.
bool restore_kill_placeholder(xcb_window_t placeholder)
Kill the placeholder window, if placeholder refers to a placeholder window.
xcb_window_t window
The X11 placeholder window.
surface_t surface
The drawable surface.
void i3string_free(i3String *str)
Free an i3String.
static TAILQ_HEAD(state_head, placeholder_state)
static struct ev_prepare * xcb_prepare
void draw_util_surface_set_size(surface_t *surface, int width, int height)
Resize the surface to the given size.
xcb_visualtype_t * get_visualtype(xcb_screen_t *screen)
Returns the visual type associated with the given screen.
#define TAILQ_EMPTY(head)
static void expose_event(xcb_expose_event_t *event)
static void update_placeholder_contents(placeholder_state *state)
static void open_placeholder_window(Con *con)
#define TAILQ_INSERT_TAIL(head, elm, field)
static void configure_notify(xcb_configure_notify_event_t *event)
void * scalloc(size_t num, size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
A "match" is a data structure which acts like a mask or expression to match certain windows or not.
int predict_text_width(i3String *text)
Predict the text width in pixels for the given text.
#define TAILQ_HEAD_INITIALIZER(head)
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
Rect rect
Current size of the placeholder window (to detect size changes).
void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_drawable_t drawable, xcb_visualtype_t *visual, int width, int height)
Initialize the surface to represent the given drawable.
#define APPEND_REGEX(re_name)
void restore_open_placeholder_windows(Con *parent)
Open placeholder windows for all children of parent.
xcb_window_t create_window(xcb_connection_t *conn, Rect dims, uint16_t depth, xcb_visualid_t visual, uint16_t window_class, enum xcursor_cursor_t cursor, bool map, uint32_t mask, uint32_t *values)
Convenience wrapper around xcb_create_window which takes care of depth, generating an ID and checking...
xcb_screen_t * root_screen
struct Config::config_client client[QUBE_NUM_LABELS]
Con * con
The container to which this placeholder window belongs.
void draw_util_clear_surface(surface_t *surface, color_t color)
Clears a surface with the given color.
void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width)
Draw the given text using libi3.
#define TAILQ_ENTRY(type)
struct ev_loop * main_loop
struct Colortriple placeholder
void restore_connect(void)
Opens a separate connection to X11 for placeholder windows when restoring layouts.
static void restore_handle_event(int type, xcb_generic_event_t *event)
static void restore_xcb_prepare_cb(EV_P_ ev_prepare *w, int revents)
int height
The height of the font, built from font_ascent + font_descent.
#define TAILQ_INSERT_HEAD(head, elm, field)
#define TAILQ_FOREACH(var, head, field)
A 'Con' represents everything from the X11 root window down to a single X11 window.
struct placeholder_state placeholder_state
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
#define TAILQ_REMOVE(head, elm, field)