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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -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
|
||||
|
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
|
||||
|
||||
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 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",
|
||||
|
21
src/con.c
21
src/con.c
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user