Fix dragging floating containers / click handling

This commit is contained in:
Michael Stapelberg 2010-12-31 01:38:17 +01:00
parent daf00a932f
commit 2d05c3a37d
5 changed files with 90 additions and 26 deletions

View File

@ -54,6 +54,13 @@ Con *con_get_fullscreen_con(Con *con);
*/
bool con_is_floating(Con *con);
/**
* 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);
/**
* Returns the container with the given client window ID or NULL if no such
* container exists.

View File

@ -53,6 +53,12 @@ void floating_disable(Con *con, bool automatic);
*/
void toggle_floating_mode(Con *con, bool automatic);
/**
* Raises the given container in the list of floating containers
*
*/
void floating_raise_con(Con *con);
#if 0
/**
* Removes the floating client from its workspace and attaches it to the new

View File

@ -237,26 +237,47 @@ static bool floating_mod_on_tiled_client(xcb_connection_t *conn, Client *client,
#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;
@ -268,11 +289,10 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
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");
@ -287,23 +307,23 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
}
}
/* click to focus */
con_focus(con);
/* 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));
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;
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 dont 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",

View File

@ -157,6 +157,7 @@ void con_detach(Con *con) {
*/
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 */
@ -170,6 +171,7 @@ void con_focus(Con *con) {
con->urgent = false;
workspace_update_urgent_flag(con_get_workspace(con));
}
DLOG("con_focus done = %p\n", con);
}
/*
@ -287,6 +289,25 @@ bool con_is_floating(Con *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.

View File

@ -172,6 +172,16 @@ void toggle_floating_mode(Con *con, bool automatic) {
floating_enable(con, automatic);
}
/*
* Raises the given container in the list of floating containers
*
*/
void floating_raise_con(Con *con) {
DLOG("Raising floating con %p / %s\n", con, con->name);
TAILQ_REMOVE(&(con->parent->floating_head), con, floating_windows);
TAILQ_INSERT_TAIL(&(con->parent->floating_head), con, floating_windows);
}
DRAGGING_CB(drag_window_callback) {
struct xcb_button_press_event_t *event = extra;