Fix dragging floating containers / click handling
This commit is contained in:
parent
daf00a932f
commit
2d05c3a37d
|
@ -54,6 +54,13 @@ Con *con_get_fullscreen_con(Con *con);
|
||||||
*/
|
*/
|
||||||
bool con_is_floating(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
|
* Returns the container with the given client window ID or NULL if no such
|
||||||
* container exists.
|
* container exists.
|
||||||
|
|
|
@ -53,6 +53,12 @@ void floating_disable(Con *con, bool automatic);
|
||||||
*/
|
*/
|
||||||
void toggle_floating_mode(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
|
#if 0
|
||||||
/**
|
/**
|
||||||
* Removes the floating client from its workspace and attaches it to the new
|
* Removes the floating client from its workspace and attaches it to the new
|
||||||
|
|
72
src/click.c
72
src/click.c
|
@ -237,26 +237,47 @@ static bool floating_mod_on_tiled_client(xcb_connection_t *conn, Client *client,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
|
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;
|
Con *con;
|
||||||
DLOG("Button %d pressed on window 0x%08x\n", event->state, event->event);
|
DLOG("Button %d pressed on window 0x%08x\n", event->state, event->event);
|
||||||
|
|
||||||
con = con_by_window_id(event->event);
|
con = con_by_window_id(event->event);
|
||||||
bool border_click = false;
|
bool border_click = (con == NULL);
|
||||||
if (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);
|
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)
|
DLOG("clicked_into = %p\n", clicked_into);
|
||||||
//con = TAILQ_FIRST(&(con->nodes_head));
|
|
||||||
|
|
||||||
/* See if this was a click with the configured modifier. If so, we need
|
/* 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
|
* to move around the client if it was floating. if not, we just process
|
||||||
* as usual. */
|
* as usual. */
|
||||||
DLOG("state = %d, floating_modifier = %d\n", event->state, config.floating_modifier);
|
DLOG("state = %d, floating_modifier = %d\n", event->state, config.floating_modifier);
|
||||||
if (border_click ||
|
if (border_click || mod_pressed) {
|
||||||
(config.floating_modifier != 0 &&
|
|
||||||
(event->state & config.floating_modifier) == config.floating_modifier)) {
|
|
||||||
if (con == NULL) {
|
if (con == NULL) {
|
||||||
LOG("Not handling, floating_modifier was pressed and no client found\n");
|
LOG("Not handling, floating_modifier was pressed and no client found\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -268,11 +289,10 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Con *floatingcon = con;
|
||||||
if ((border_click && con->type == CT_FLOATING_CON) ||
|
if ((border_click && con->type == CT_FLOATING_CON) ||
|
||||||
(!border_click && con_is_floating(con))) {
|
((floatingcon = con_inside_floating(con)) != NULL &&
|
||||||
/* floating operations are always on the container around
|
clicked_into == NULL)) {
|
||||||
* the "payload container", so make sure we use the right one */
|
|
||||||
Con *floatingcon = (border_click ? con : con->parent);
|
|
||||||
LOG("button %d pressed\n", event->detail);
|
LOG("button %d pressed\n", event->detail);
|
||||||
if (event->detail == 1) {
|
if (event->detail == 1) {
|
||||||
LOG("left mouse button, dragging\n");
|
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 */
|
/* click to focus, either on the clicked window or its child if thas was a
|
||||||
con_focus(con);
|
* click into a child decoration */
|
||||||
|
con_focus((clicked_into ? clicked_into : con));
|
||||||
|
|
||||||
Con *clicked_into = NULL;
|
/* for floating containers, we also want to raise them on click */
|
||||||
|
Con *floatingcon = con_inside_floating(con);
|
||||||
Con *child;
|
if (floatingcon != NULL)
|
||||||
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
|
floating_raise_con(floatingcon);
|
||||||
if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
clicked_into = child;
|
|
||||||
con_focus(child);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tree_render();
|
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) */
|
/* check if this was a click on the window border (and on which one) */
|
||||||
Rect bsr = con_border_style_rect(con);
|
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",
|
DLOG("BORDER x = %d, y = %d for con %p, window 0x%08x, border_click = %d, clicked_into = %p\n",
|
||||||
|
|
21
src/con.c
21
src/con.c
|
@ -157,6 +157,7 @@ void con_detach(Con *con) {
|
||||||
*/
|
*/
|
||||||
void con_focus(Con *con) {
|
void con_focus(Con *con) {
|
||||||
assert(con != NULL);
|
assert(con != NULL);
|
||||||
|
DLOG("con_focus = %p\n", con);
|
||||||
|
|
||||||
/* 1: set focused-pointer to the new 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 */
|
/* 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;
|
con->urgent = false;
|
||||||
workspace_update_urgent_flag(con_get_workspace(con));
|
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);
|
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
|
* Returns the container with the given client window ID or NULL if no such
|
||||||
* container exists.
|
* container exists.
|
||||||
|
|
|
@ -172,6 +172,16 @@ void toggle_floating_mode(Con *con, bool automatic) {
|
||||||
floating_enable(con, 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) {
|
DRAGGING_CB(drag_window_callback) {
|
||||||
struct xcb_button_press_event_t *event = extra;
|
struct xcb_button_press_event_t *event = extra;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue