static xcb_window_t *btt_stack;
static int btt_stack_num;
+/* Stores coordinates to warp mouse pointer to if set */
+static Rect *warp_to;
+
/*
* Describes the X11 state we may modify (map state, position, window stack).
* There is one entry per container. The state represents the current situation
*/
void x_draw_decoration(Con *con) {
Con *parent = con->parent;
+ bool leaf = con_is_leaf(con);
/* This code needs to run for:
* • leaf containers
* • non-leaf containers which are in a stacked/tabbed container
* It does not need to run for:
* • floating containers (they don’t have a decoration)
*/
- if ((!con_is_leaf(con) &&
+ if ((!leaf &&
parent->layout != L_STACKED &&
parent->layout != L_TABBED) ||
con->type == CT_FLOATING_CON)
/* Skip containers whose pixmap has not yet been created (can happen when
* decoration rendering happens recursively for a window for which
* x_push_node() was not yet called) */
- if (con->pixmap == XCB_NONE) {
+ if (leaf && con->pixmap == XCB_NONE) {
DLOG("pixmap not yet created, not rendering\n");
return;
}
/* find out which colors to use */
if (con->urgent)
p->color = &config.client.urgent;
- else if (con == focused)
+ else if (con == focused || con_inside_focused(con))
p->color = &config.client.focused;
else if (con == TAILQ_FIRST(&(parent->focus_head)))
p->color = &config.client.focused_inactive;
xcb_change_gc_single(conn, parent->pm_gc, XCB_GC_FOREGROUND, p->color->border);
Rect *dr = &(con->deco_rect);
xcb_segment_t segments[] = {
- { dr->x, dr->y,
- dr->x + dr->width, dr->y },
+ { dr->x, dr->y,
+ dr->x + dr->width - 1, dr->y },
- { dr->x, dr->y + dr->height - 1,
- dr->x + dr->width, dr->y + dr->height - 1 }
+ { dr->x + 2, dr->y + dr->height - 1,
+ dr->x + dr->width - 3, dr->y + dr->height - 1 }
};
xcb_poly_segment(conn, parent->pixmap, parent->pm_gc, 2, segments);
}
if ((con->type != CT_ROOT && con->type != CT_OUTPUT) &&
- con->mapped)
+ (!leaf || con->mapped))
x_draw_decoration(con);
}
DLOG("pushing name %s for con %p\n", state->name, con);
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->frame,
- A_WM_NAME, A_STRING, 8, strlen(state->name), state->name);
+ XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(state->name), state->name);
FREE(state->name);
}
*/
void x_push_changes(Con *con) {
con_state *state;
+ xcb_query_pointer_cookie_t pointercookie;
+
+ /* If we need to warp later, we request the pointer position as soon as possible */
+ if (warp_to) {
+ pointercookie = xcb_query_pointer(conn, root);
+ }
DLOG("-- PUSHING WINDOW STACK --\n");
//DLOG("Disabling EnterNotify\n");
}
//DLOG("Done, EnterNotify disabled\n");
bool order_changed = false;
+ bool stacking_changed = false;
/* count first, necessary to (re)allocate memory for the bottom-to-top
* stack afterwards */
//DLOG("stack: 0x%08x\n", state->id);
con_state *prev = CIRCLEQ_PREV(state, state);
con_state *old_prev = CIRCLEQ_PREV(state, old_state);
- if ((prev != old_prev || state->initial) && prev != CIRCLEQ_END(&state_head)) {
+ if (prev != old_prev)
order_changed = true;
+ if ((state->initial || order_changed) && prev != CIRCLEQ_END(&state_head)) {
+ stacking_changed = true;
DLOG("Stacking 0x%08x above 0x%08x\n", prev->id, state->id);
uint32_t mask = 0;
mask |= XCB_CONFIG_WINDOW_SIBLING;
/* If we re-stacked something (or a new window appeared), we need to update
* the _NET_CLIENT_LIST_STACKING hint */
- if (order_changed)
+ if (stacking_changed)
ewmh_update_client_list_stacking(btt_stack, btt_stack_num);
+ DLOG("\n\n PUSHING CHANGES\n\n");
+ x_push_node(con);
+
//DLOG("Re-enabling EnterNotify\n");
values[0] = FRAME_EVENT_MASK;
CIRCLEQ_FOREACH_REVERSE(state, &state_head, state) {
}
//DLOG("Done, EnterNotify re-enabled\n");
- DLOG("\n\n PUSHING CHANGES\n\n");
- x_push_node(con);
x_deco_recurse(con);
xcb_window_t to_focus = focused->frame;
focused_id = root;
}
+ if (warp_to) {
+ xcb_query_pointer_reply_t *pointerreply = xcb_query_pointer_reply(conn, pointercookie, NULL);
+ if (!pointerreply) {
+ ELOG("Could not query pointer position, not warping pointer\n");
+ } else {
+ int mid_x = warp_to->x + (warp_to->width / 2);
+ int mid_y = warp_to->y + (warp_to->height / 2);
+
+ Output *current = get_output_containing(pointerreply->root_x, pointerreply->root_y);
+ Output *target = get_output_containing(mid_x, mid_y);
+ if (current != target)
+ xcb_warp_pointer(conn, XCB_NONE, root, 0, 0, 0, 0, mid_x, mid_y);
+ }
+ warp_to = NULL;
+ }
+
xcb_flush(conn);
DLOG("\n\n ENDING CHANGES\n\n");
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A_I3_CONFIG_PATH, A_UTF8_STRING, 8,
strlen(current_configpath), current_configpath);
}
+
+/*
+ * Set warp_to coordinates. This will trigger on the next call to
+ * x_push_changes().
+ *
+ */
+void x_set_warp_to(Rect *rect)
+{
+ warp_to = rect;
+}