Tiling resize drag: use threshold

This commit is contained in:
Albert Safin 2018-12-12 20:53:53 +07:00
parent c6b56b09ab
commit 371dc23101
3 changed files with 59 additions and 41 deletions

View File

@ -13,7 +13,9 @@
bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides); bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides);
void resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event); void resize_graphical_handler(Con *first, Con *second, orientation_t orientation,
const xcb_button_press_event_t *event,
bool use_threshold);
/** /**
* Resize the two given containers using the given amount of pixels or * Resize the two given containers using the given amount of pixels or

View File

@ -26,7 +26,7 @@ typedef enum { CLICK_BORDER = 0,
* then calls resize_graphical_handler(). * then calls resize_graphical_handler().
* *
*/ */
static bool tiling_resize_for_border(Con *con, border_t border, xcb_button_press_event_t *event) { static bool tiling_resize_for_border(Con *con, border_t border, xcb_button_press_event_t *event, bool use_threshold) {
DLOG("border = %d, con = %p\n", border, con); DLOG("border = %d, con = %p\n", border, con);
Con *second = NULL; Con *second = NULL;
Con *first = con; Con *first = con;
@ -64,7 +64,7 @@ static bool tiling_resize_for_border(Con *con, border_t border, xcb_button_press
const orientation_t orientation = ((border == BORDER_LEFT || border == BORDER_RIGHT) ? HORIZ : VERT); const orientation_t orientation = ((border == BORDER_LEFT || border == BORDER_RIGHT) ? HORIZ : VERT);
resize_graphical_handler(first, second, orientation, event); resize_graphical_handler(first, second, orientation, event, use_threshold);
DLOG("After resize handler, rendering\n"); DLOG("After resize handler, rendering\n");
tree_render(); tree_render();
@ -94,22 +94,22 @@ static bool floating_mod_on_tiled_client(Con *con, xcb_button_press_event_t *eve
if (to_right < to_left && if (to_right < to_left &&
to_right < to_top && to_right < to_top &&
to_right < to_bottom) to_right < to_bottom)
return tiling_resize_for_border(con, BORDER_RIGHT, event); return tiling_resize_for_border(con, BORDER_RIGHT, event, false);
if (to_left < to_right && if (to_left < to_right &&
to_left < to_top && to_left < to_top &&
to_left < to_bottom) to_left < to_bottom)
return tiling_resize_for_border(con, BORDER_LEFT, event); return tiling_resize_for_border(con, BORDER_LEFT, event, false);
if (to_top < to_right && if (to_top < to_right &&
to_top < to_left && to_top < to_left &&
to_top < to_bottom) to_top < to_bottom)
return tiling_resize_for_border(con, BORDER_TOP, event); return tiling_resize_for_border(con, BORDER_TOP, event, false);
if (to_bottom < to_right && if (to_bottom < to_right &&
to_bottom < to_left && to_bottom < to_left &&
to_bottom < to_top) to_bottom < to_top)
return tiling_resize_for_border(con, BORDER_BOTTOM, event); return tiling_resize_for_border(con, BORDER_BOTTOM, event, false);
return false; return false;
} }
@ -118,45 +118,26 @@ static bool floating_mod_on_tiled_client(Con *con, xcb_button_press_event_t *eve
* Finds out which border was clicked on and calls tiling_resize_for_border(). * Finds out which border was clicked on and calls tiling_resize_for_border().
* *
*/ */
static bool tiling_resize(Con *con, xcb_button_press_event_t *event, const click_destination_t dest) { static bool tiling_resize(Con *con, xcb_button_press_event_t *event, const click_destination_t dest, bool use_threshold) {
/* 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\n", DLOG("BORDER x = %d, y = %d for con %p, window 0x%08x\n",
event->event_x, event->event_y, con, event->event); event->event_x, event->event_y, con, event->event);
DLOG("checks for right >= %d\n", con->window_rect.x + con->window_rect.width); DLOG("checks for right >= %d\n", con->window_rect.x + con->window_rect.width);
if (dest == CLICK_DECORATION) { if (dest == CLICK_DECORATION) {
/* The user clicked on a window decoration. We ignore the following case: return tiling_resize_for_border(con, BORDER_TOP, event, use_threshold);
* The container is a h-split, tabbed or stacked container with > 1
* window. Decorations will end up next to each other and the user
* expects to switch to a window by clicking on its decoration. */
/* Since the container might either be the child *or* already a split
* container (in the case of a nested split container), we need to make
* sure that we are dealing with the split container here. */
Con *check_con = con;
if (con_is_leaf(check_con) && check_con->parent->type == CT_CON)
check_con = check_con->parent;
if ((check_con->layout == L_STACKED ||
check_con->layout == L_TABBED ||
con_orientation(check_con) == HORIZ) &&
con_num_children(check_con) > 1) {
DLOG("Not handling this resize, this container has > 1 child.\n");
return false;
}
return tiling_resize_for_border(con, BORDER_TOP, event);
} }
if (event->event_x >= 0 && event->event_x <= (int32_t)bsr.x && if (event->event_x >= 0 && event->event_x <= (int32_t)bsr.x &&
event->event_y >= (int32_t)bsr.y && event->event_y <= (int32_t)(con->rect.height + bsr.height)) event->event_y >= (int32_t)bsr.y && event->event_y <= (int32_t)(con->rect.height + bsr.height))
return tiling_resize_for_border(con, BORDER_LEFT, event); return tiling_resize_for_border(con, BORDER_LEFT, event, false);
if (event->event_x >= (int32_t)(con->window_rect.x + con->window_rect.width) && if (event->event_x >= (int32_t)(con->window_rect.x + con->window_rect.width) &&
event->event_y >= (int32_t)bsr.y && event->event_y <= (int32_t)(con->rect.height + bsr.height)) event->event_y >= (int32_t)bsr.y && event->event_y <= (int32_t)(con->rect.height + bsr.height))
return tiling_resize_for_border(con, BORDER_RIGHT, event); return tiling_resize_for_border(con, BORDER_RIGHT, event, false);
if (event->event_y >= (int32_t)(con->window_rect.y + con->window_rect.height)) if (event->event_y >= (int32_t)(con->window_rect.y + con->window_rect.height))
return tiling_resize_for_border(con, BORDER_BOTTOM, event); return tiling_resize_for_border(con, BORDER_BOTTOM, event, false);
return false; return false;
} }
@ -276,7 +257,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
is_left_or_right_click) { is_left_or_right_click) {
/* try tiling resize, but continue if it doesnt work */ /* try tiling resize, but continue if it doesnt work */
DLOG("tiling resize with fallback\n"); DLOG("tiling resize with fallback\n");
if (tiling_resize(con, event, dest)) if (tiling_resize(con, event, dest, !was_focused))
goto done; goto done;
} }
@ -311,7 +292,11 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
else if ((dest == CLICK_BORDER || dest == CLICK_DECORATION) && else if ((dest == CLICK_BORDER || dest == CLICK_DECORATION) &&
is_left_or_right_click) { is_left_or_right_click) {
DLOG("Trying to resize (tiling)\n"); DLOG("Trying to resize (tiling)\n");
tiling_resize(con, event, dest); /* Since we updated the tree (con_activate() above), we need to
* re-render the tree before returning to the event loop (drag_pointer()
* inside tiling_resize() runs its own event-loop). */
tree_render();
tiling_resize(con, event, dest, dest == CLICK_DECORATION && !was_focused);
} }
done: done:

View File

@ -21,12 +21,32 @@ struct callback_params {
Con *output; Con *output;
xcb_window_t helpwin; xcb_window_t helpwin;
uint32_t *new_position; uint32_t *new_position;
bool *threshold_exceeded;
}; };
DRAGGING_CB(resize_callback) { DRAGGING_CB(resize_callback) {
const struct callback_params *params = extra; const struct callback_params *params = extra;
Con *output = params->output; Con *output = params->output;
DLOG("new x = %d, y = %d\n", new_x, new_y); DLOG("new x = %d, y = %d\n", new_x, new_y);
if (!*params->threshold_exceeded) {
xcb_map_window(conn, params->helpwin);
/* Warp pointer in the same way as resize_graphical_handler() would do
* if threshold wasn't enabled, but also take into account travelled
* distance. */
if (params->orientation == HORIZ) {
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
*params->new_position + new_x - event->root_x,
new_y);
} else {
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
new_x,
*params->new_position + new_y - event->root_y);
}
*params->threshold_exceeded = true;
return;
}
if (params->orientation == HORIZ) { if (params->orientation == HORIZ) {
/* Check if the new coordinates are within screen boundaries */ /* Check if the new coordinates are within screen boundaries */
if (new_x > (output->rect.x + output->rect.width - 25) || if (new_x > (output->rect.x + output->rect.width - 25) ||
@ -148,7 +168,9 @@ bool resize_neighboring_cons(Con *first, Con *second, int px, int ppt) {
return true; return true;
} }
void resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event) { void resize_graphical_handler(Con *first, Con *second, orientation_t orientation,
const xcb_button_press_event_t *event,
bool use_threshold) {
Con *output = con_get_output(first); Con *output = con_get_output(first);
DLOG("x = %d, width = %d\n", output->rect.x, output->rect.width); DLOG("x = %d, width = %d\n", output->rect.x, output->rect.width);
@ -179,14 +201,10 @@ void resize_graphical_handler(Con *first, Con *second, orientation_t orientation
helprect.width = logical_px(2); helprect.width = logical_px(2);
helprect.height = second->rect.height; helprect.height = second->rect.height;
initial_position = second->rect.x; initial_position = second->rect.x;
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
second->rect.x, event->root_y);
} else { } else {
helprect.width = second->rect.width; helprect.width = second->rect.width;
helprect.height = logical_px(2); helprect.height = logical_px(2);
initial_position = second->rect.y; initial_position = second->rect.y;
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
event->root_x, second->rect.y);
} }
mask = XCB_CW_BACK_PIXEL; mask = XCB_CW_BACK_PIXEL;
@ -196,7 +214,18 @@ void resize_graphical_handler(Con *first, Con *second, orientation_t orientation
values[1] = 1; values[1] = 1;
xcb_window_t helpwin = create_window(conn, helprect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT, xcb_window_t helpwin = create_window(conn, helprect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
XCB_WINDOW_CLASS_INPUT_OUTPUT, (orientation == HORIZ ? XCURSOR_CURSOR_RESIZE_HORIZONTAL : XCURSOR_CURSOR_RESIZE_VERTICAL), true, mask, values); XCB_WINDOW_CLASS_INPUT_OUTPUT, (orientation == HORIZ ? XCURSOR_CURSOR_RESIZE_HORIZONTAL : XCURSOR_CURSOR_RESIZE_VERTICAL), false, mask, values);
if (!use_threshold) {
xcb_map_window(conn, helpwin);
if (orientation == HORIZ) {
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
second->rect.x, event->root_y);
} else {
xcb_warp_pointer(conn, XCB_NONE, event->root, 0, 0, 0, 0,
event->root_x, second->rect.y);
}
}
xcb_circulate_window(conn, XCB_CIRCULATE_RAISE_LOWEST, helpwin); xcb_circulate_window(conn, XCB_CIRCULATE_RAISE_LOWEST, helpwin);
@ -205,10 +234,12 @@ void resize_graphical_handler(Con *first, Con *second, orientation_t orientation
/* `new_position' will be updated by the `resize_callback'. */ /* `new_position' will be updated by the `resize_callback'. */
new_position = initial_position; new_position = initial_position;
const struct callback_params params = {orientation, output, helpwin, &new_position}; bool threshold_exceeded = !use_threshold;
const struct callback_params params = {orientation, output, helpwin, &new_position, &threshold_exceeded};
/* `drag_pointer' blocks until the drag is completed. */ /* `drag_pointer' blocks until the drag is completed. */
drag_result_t drag_result = drag_pointer(NULL, event, grabwin, 0, false, resize_callback, &params); drag_result_t drag_result = drag_pointer(NULL, event, grabwin, 0, use_threshold, resize_callback, &params);
xcb_destroy_window(conn, helpwin); xcb_destroy_window(conn, helpwin);
xcb_destroy_window(conn, grabwin); xcb_destroy_window(conn, grabwin);