uint32_t height;
} __attribute__((packed));
+/**
+ * Stores the reserved pixels on each screen edge read from a
+ * _NET_WM_STRUT_PARTIAL.
+ *
+ */
+struct reservedpx {
+ uint32_t left;
+ uint32_t right;
+ uint32_t top;
+ uint32_t bottom;
+};
+
/**
* Used for the cache of colorpixels.
*
bool uses_net_wm_name;
/** Whether the window says it is a dock window */
- bool dock;
+ enum { W_NODOCK = 0, W_DOCK_TOP = 1, W_DOCK_BOTTOM = 2 } dock;
+
+ /** Pixels the window reserves. left/right/top/bottom */
+ struct reservedpx reserved;
};
struct Match {
char *class;
char *instance;
char *mark;
- int dock;
+ enum {
+ M_DONTCHECK = -1,
+ M_NODOCK = 0,
+ M_DOCK_ANY = 1,
+ M_DOCK_TOP = 2,
+ M_DOCK_BOTTOM = 3
+ } dock;
xcb_window_t id;
Con *con_id;
enum { M_ANY = 0, M_TILING, M_FLOATING } floating;
*/
void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop);
+/**
+ * Updates the _NET_WM_STRUT_PARTIAL (reserved pixels at the screen edges)
+ *
+ */
+void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop);
+
#endif
}
}
- /* Insert the container after the tiling container, if found */
- if (current) {
+ /* Insert the container after the tiling container, if found.
+ * When adding to a CT_OUTPUT, just append one after another. */
+ if (current && parent->type != CT_OUTPUT) {
DLOG("Inserting con = %p after last focused tiling con %p\n",
con, current);
TAILQ_INSERT_AFTER(nodes_head, current, con, nodes);
window_update_name(cwindow, xcb_get_property_reply(conn, utf8_title_cookie, NULL));
window_update_leader(cwindow, xcb_get_property_reply(conn, leader_cookie, NULL));
window_update_transient_for(cwindow, xcb_get_property_reply(conn, transient_cookie, NULL));
+ window_update_strut_partial(cwindow, xcb_get_property_reply(conn, strut_cookie, NULL));
+
+ /* Where to start searching for a container that swallows the new one? */
+ Con *search_at = croot;
xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, wm_type_cookie, NULL);
if (xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_DOCK])) {
- cwindow->dock = true;
- LOG("this window is a dock\n");
+ LOG("This window is of type dock\n");
+ Output *output = get_output_containing(geom->x, geom->y);
+ if (output != NULL) {
+ DLOG("Starting search at output %s\n", output->name);
+ search_at = output->con;
+ }
+
+ /* find out the desired position of this dock window */
+ if (cwindow->reserved.top > 0 && cwindow->reserved.bottom == 0) {
+ DLOG("Top dock client\n");
+ cwindow->dock = W_DOCK_TOP;
+ } else if (cwindow->reserved.top == 0 && cwindow->reserved.bottom > 0) {
+ DLOG("Bottom dock client\n");
+ cwindow->dock = W_DOCK_BOTTOM;
+ } else {
+ DLOG("Ignoring invalid reserved edges (_NET_WM_STRUT_PARTIAL), using position as fallback:\n");
+ if (geom->y < (search_at->rect.height / 2)) {
+ DLOG("geom->y = %d < rect.height / 2 = %d, it is a top dock client\n",
+ geom->y, (search_at->rect.height / 2));
+ cwindow->dock = W_DOCK_TOP;
+ } else {
+ DLOG("geom->y = %d >= rect.height / 2 = %d, it is a bottom dock client\n",
+ geom->y, (search_at->rect.height / 2));
+ cwindow->dock = W_DOCK_BOTTOM;
+ }
+ }
}
DLOG("Initial geometry: (%d, %d, %d, %d)\n", geom->x, geom->y, geom->width, geom->height);
/* TODO: two matches for one container */
/* See if any container swallows this new window */
- Con *search_at = croot;
- if (cwindow->dock) {
- /* for dock windows, we start the search at the appropriate output */
- Output *output = get_output_containing(geom->x, geom->y);
- if (output != NULL) {
- DLOG("Starting search at output %s\n", output->name);
- search_at = output->con;
- }
- }
nc = con_for_window(search_at, cwindow, &match);
if (nc == NULL) {
if (focused->type == CT_CON && con_accepts_window(focused)) {
}
LOG("match->dock = %d, window->dock = %d\n", match->dock, window->dock);
- if (match->dock != -1 && window->dock == match->dock) {
+ if (match->dock != -1 &&
+ ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
+ (window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) ||
+ ((window->dock == W_DOCK_TOP || window->dock == W_DOCK_BOTTOM) &&
+ match->dock == M_DOCK_ANY) ||
+ (window->dock == W_NODOCK && match->dock == M_NODOCK))) {
LOG("match made by dock\n");
return true;
}
/* this container swallows dock clients */
Match *match = scalloc(sizeof(Match));
match_init(match);
- match->dock = true;
+ match->dock = M_DOCK_TOP;
match->insert_where = M_BELOW;
TAILQ_INSERT_TAIL(&(topdock->swallow_head), match, matches);
DLOG("attaching\n");
con_attach(topdock, con, false);
+ /* content container */
+
DLOG("adding main content container\n");
Con *content = con_new(NULL);
content->type = CT_CON;
FREE(name);
con_attach(content, con, false);
+ /* bottom dock container */
+ Con *bottomdock = con_new(NULL);
+ bottomdock->type = CT_DOCKAREA;
+ bottomdock->layout = L_DOCKAREA;
+ bottomdock->orientation = VERT;
+ /* this container swallows dock clients */
+ match = scalloc(sizeof(Match));
+ match_init(match);
+ match->dock = M_DOCK_BOTTOM;
+ match->insert_where = M_BELOW;
+ TAILQ_INSERT_TAIL(&(bottomdock->swallow_head), match, matches);
+
+ bottomdock->name = sstrdup("bottomdock");
+
+ asprintf(&name, "[i3 con] bottom dockarea %s", con->name);
+ x_set_name(bottomdock, name);
+ FREE(name);
+ DLOG("attaching\n");
+ con_attach(bottomdock, con, false);
+
DLOG("Now adding a workspace\n");
/* add a workspace to this output */
win->name_len = strlen(new_name);
}
-/**
+/*
* Updates the CLIENT_LEADER (logical parent window).
*
*/
win->leader = *leader;
}
-/**
+/*
* Updates the TRANSIENT_FOR (logical parent window).
*
*/
win->transient_for = transient_for;
}
+
+/*
+ * Updates the _NET_WM_STRUT_PARTIAL (reserved pixels at the screen edges)
+ *
+ */
+void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop) {
+ if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
+ DLOG("prop == NULL\n");
+ return;
+ }
+
+ uint32_t *strut;
+ if (!(strut = xcb_get_property_value(prop)))
+ return;
+
+ DLOG("Reserved pixels changed to: left = %d, right = %d, top = %d, bottom = %d\n",
+ strut[0], strut[1], strut[2], strut[3]);
+
+ win->reserved = (struct reservedpx){ strut[0], strut[1], strut[2], strut[3] };
+}