#endif
int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
+ /* TODO: dragging floating windows by grabbing their decoration does not
+ * work right now. We need to somehow recognize that special case: either
+ * we check if the con with the clicked decoration is the only con inside
+ * its parent (so that you can only drag single floating windows, not
+ * floating containers with multiple windows) *or* we somehow find out
+ * which decoration(s) are at the top and enable grabbing for them while
+ * resizing for the others. Maybe we could process the resizing parameters
+ * first and check if resizing is possible: if yes, resize, if not, drag.
+ *
+ * Also raise on click on decoration is not working. */
Con *con;
DLOG("Button %d pressed on window 0x%08x\n", event->state, event->event);
con = con_by_window_id(event->event);
- bool border_click = false;
- if (con == NULL) {
+ bool border_click = (con == NULL);
+ const uint32_t mod = config.floating_modifier;
+ bool mod_pressed = (mod != 0 && (event->state & mod) == mod);
+
+ if (border_click)
con = con_by_frame_id(event->event);
- border_click = true;
+
+ DLOG("border_click = %d, mod_pressed = %d\n", border_click, mod_pressed);
+
+ Con *clicked_into = NULL;
+
+ Con *child;
+ TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
+ if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
+ continue;
+
+ clicked_into = child;
+ break;
}
- DLOG("border_click = %d\n", border_click);
- //if (con && con->type == CT_FLOATING_CON)
- //con = TAILQ_FIRST(&(con->nodes_head));
+
+ DLOG("clicked_into = %p\n", clicked_into);
/* See if this was a click with the configured modifier. If so, we need
* to move around the client if it was floating. if not, we just process
* as usual. */
DLOG("state = %d, floating_modifier = %d\n", event->state, config.floating_modifier);
- if (border_click ||
- (config.floating_modifier != 0 &&
- (event->state & config.floating_modifier) == config.floating_modifier)) {
+ if (border_click || mod_pressed) {
if (con == NULL) {
LOG("Not handling, floating_modifier was pressed and no client found\n");
return 1;
return 1;
}
#endif
+ Con *floatingcon = con;
if ((border_click && con->type == CT_FLOATING_CON) ||
- (!border_click && con_is_floating(con))) {
- /* floating operations are always on the container around
- * the "payload container", so make sure we use the right one */
- Con *floatingcon = (border_click ? con : con->parent);
+ ((floatingcon = con_inside_floating(con)) != NULL &&
+ clicked_into == NULL)) {
LOG("button %d pressed\n", event->detail);
if (event->detail == 1) {
LOG("left mouse button, dragging\n");
}
}
- /* click to focus */
- con_focus(con);
-
- Con *clicked_into = NULL;
-
- Con *child;
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
- if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
- continue;
+ /* click to focus, either on the clicked window or its child if thas was a
+ * click into a child decoration */
+ con_focus((clicked_into ? clicked_into : con));
- clicked_into = child;
- con_focus(child);
- break;
- }
+ /* for floating containers, we also want to raise them on click */
+ Con *floatingcon = con_inside_floating(con);
+ if (floatingcon != NULL)
+ floating_raise_con(floatingcon);
tree_render();
+ /* if we clicked into a child decoration on a stacked/tabbed container, we
+ * are done and don’t want to resize */
+ if (clicked_into &&
+ (con->layout == L_STACKED || con->layout == L_TABBED))
+ return 1;
+
/* check if this was a click on the window border (and on which one) */
Rect bsr = con_border_style_rect(con);
DLOG("BORDER x = %d, y = %d for con %p, window 0x%08x, border_click = %d, clicked_into = %p\n",
*/
void con_focus(Con *con) {
assert(con != NULL);
+ DLOG("con_focus = %p\n", con);
/* 1: set focused-pointer to the new con */
/* 2: exchange the position of the container in focus stack of the parent all the way up */
con->urgent = false;
workspace_update_urgent_flag(con_get_workspace(con));
}
+ DLOG("con_focus done = %p\n", con);
}
/*
return (con->floating >= FLOATING_AUTO_ON);
}
+/*
+ * Checks if the given container is either floating or inside some floating
+ * container. It returns the FLOATING_CON container.
+ *
+ */
+Con *con_inside_floating(Con *con) {
+ assert(con != NULL);
+ if (con->type == CT_FLOATING_CON)
+ return con;
+
+ if (con->floating >= FLOATING_AUTO_ON)
+ return con->parent;
+
+ if (con->type == CT_WORKSPACE)
+ return NULL;
+
+ return con_inside_floating(con->parent);
+}
+
/*
* Returns the container with the given client window ID or NULL if no such
* container exists.