bool mapped;
bool unmap_now;
bool child_mapped;
+ bool is_hidden;
/** The con for which this state is. */
Con *con;
if (win_colormap != XCB_NONE)
xcb_free_colormap(conn, win_colormap);
- struct con_state *state = scalloc(sizeof(struct con_state));
+ struct con_state *state = scalloc(1, sizeof(struct con_state));
state->id = con->frame;
state->mapped = false;
state->initial = true;
/* Every X11 event is 32 bytes long. Therefore, XCB will copy 32 bytes.
* In order to properly initialize these bytes, we allocate 32 bytes even
* though we only need less for an xcb_configure_notify_event_t */
- void *event = scalloc(32);
+ void *event = scalloc(32, 1);
xcb_client_message_event_t *ev = event;
ev->response_type = XCB_CLIENT_MESSAGE;
free(event);
}
+static i3String *parse_title_format(struct Window *win) {
+ /* We need to ensure that we only escape the window title if pango
+ * is used by the current font. */
+ const bool is_markup = font_is_pango();
+
+ char *format = win->title_format;
+ /* We initialize these lazily so we only escape them if really necessary. */
+ const char *escaped_title = NULL;
+ const char *escaped_class = NULL;
+ const char *escaped_instance = NULL;
+
+ /* We have to first iterate over the string to see how much buffer space
+ * we need to allocate. */
+ int buffer_len = strlen(format) + 1;
+ for (char *walk = format; *walk != '\0'; walk++) {
+ if (STARTS_WITH(walk, "%title")) {
+ if (escaped_title == NULL)
+ escaped_title = i3string_as_utf8(is_markup ? i3string_escape_markup(win->name) : win->name);
+
+ buffer_len = buffer_len - strlen("%title") + strlen(escaped_title);
+ walk += strlen("%title") - 1;
+ } else if (STARTS_WITH(walk, "%class")) {
+ if (escaped_class == NULL)
+ escaped_class = is_markup ? g_markup_escape_text(win->class_class, -1) : win->class_class;
+
+ buffer_len = buffer_len - strlen("%class") + strlen(escaped_class);
+ walk += strlen("%class") - 1;
+ } else if (STARTS_WITH(walk, "%instance")) {
+ if (escaped_instance == NULL)
+ escaped_instance = is_markup ? g_markup_escape_text(win->class_instance, -1) : win->class_instance;
+
+ buffer_len = buffer_len - strlen("%instance") + strlen(escaped_instance);
+ walk += strlen("%instance") - 1;
+ }
+ }
+
+ /* Now we can parse the format string. */
+ char buffer[buffer_len];
+ char *outwalk = buffer;
+ for (char *walk = format; *walk != '\0'; walk++) {
+ if (*walk != '%') {
+ *(outwalk++) = *walk;
+ continue;
+ }
+
+ if (STARTS_WITH(walk + 1, "title")) {
+ outwalk += sprintf(outwalk, "%s", escaped_title);
+ walk += strlen("title");
+ } else if (STARTS_WITH(walk + 1, "class")) {
+ outwalk += sprintf(outwalk, "%s", escaped_class);
+ walk += strlen("class");
+ } else if (STARTS_WITH(walk + 1, "instance")) {
+ outwalk += sprintf(outwalk, "%s", escaped_instance);
+ walk += strlen("instance");
+ }
+ }
+ *outwalk = '\0';
+
+ i3String *formatted = i3string_from_utf8(buffer);
+ i3string_set_markup(formatted, is_markup);
+ return formatted;
+}
+
/*
* Draws the decoration of the given container onto its parent.
*
return;
/* 1: build deco_params and compare with cache */
- struct deco_render_params *p = scalloc(sizeof(struct deco_render_params));
+ struct deco_render_params *p = scalloc(1, sizeof(struct deco_render_params));
/* find out which colors to use */
if (con->urgent)
I3STRING_FREE(mark);
}
- draw_text(win->name,
+ i3String *title = win->title_format == NULL ? win->name : parse_title_format(win);
+ draw_text(title,
parent->pixmap, parent->pm_gc,
con->deco_rect.x + logical_px(2) + indent_px, con->deco_rect.y + text_offset_y,
con->deco_rect.width - logical_px(2) - indent_px - mark_width - logical_px(2));
+ if (win->title_format != NULL)
+ I3STRING_FREE(title);
after_title:
/* Since we don’t clip the text at all, it might in some cases be painted
x_draw_decoration(con);
}
+/*
+ * Sets or removes the _NET_WM_STATE_HIDDEN property on con if necessary.
+ *
+ */
+static void set_hidden_state(Con *con) {
+ if (con->window == NULL) {
+ return;
+ }
+
+ con_state *state = state_for_frame(con->frame);
+ bool should_be_hidden = con_is_hidden(con);
+ if (should_be_hidden == state->is_hidden)
+ return;
+
+ unsigned int num = 0;
+ uint32_t values[1];
+ if (should_be_hidden) {
+ DLOG("setting _NET_WM_STATE_HIDDEN for con = %p\n", con);
+ values[num++] = A__NET_WM_STATE_HIDDEN;
+ } else {
+ DLOG("removing _NET_WM_STATE_HIDDEN for con = %p\n", con);
+ }
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id, A__NET_WM_STATE, XCB_ATOM_ATOM, 32, num, values);
+ state->is_hidden = should_be_hidden;
+}
+
/*
* This function pushes the properties of each node of the layout tree to
* X11 if they have changed (like the map state, position of the window, …).
fake_absolute_configure_notify(con);
}
+ set_hidden_state(con);
+
/* Handle all children and floating windows of this node. We recurse
* in focus order to display the focused client in a stack first when
* switching workspaces (reduces flickering). */