Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'vanilla/next' into gaps-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Airblader committed Oct 9, 2019
2 parents 36fc859 + 5e1094e commit f9c80ac
Show file tree
Hide file tree
Showing 12 changed files with 439 additions and 301 deletions.
2 changes: 2 additions & 0 deletions Makefile.am
Expand Up @@ -503,6 +503,7 @@ i3_SOURCES = \
include/con.h \
include/data.h \
include/display_version.h \
include/drag.h \
include/ewmh.h \
include/fake_outputs.h \
include/floating.h \
Expand Down Expand Up @@ -548,6 +549,7 @@ i3_SOURCES = \
src/config_directives.c \
src/config_parser.c \
src/display_version.c \
src/drag.c \
src/ewmh.c \
src/fake_outputs.c \
src/floating.c \
Expand Down
1 change: 1 addition & 0 deletions include/all.h
Expand Up @@ -53,6 +53,7 @@
#include "click.h"
#include "key_press.h"
#include "floating.h"
#include "drag.h"
#include "configuration.h"
#include "handlers.h"
#include "randr.h"
Expand Down
61 changes: 61 additions & 0 deletions include/drag.h
@@ -0,0 +1,61 @@
/*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
* © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* drag.c: click and drag.
*
*/
#pragma once

#include <config.h>

/** Callback for dragging */
typedef void (*callback_t)(Con *, Rect *, uint32_t, uint32_t,
const xcb_button_press_event_t *, const void *);

/** Macro to create a callback function for dragging */
#define DRAGGING_CB(name) \
static void name(Con *con, Rect *old_rect, uint32_t new_x, uint32_t new_y, \
const xcb_button_press_event_t *event, const void *extra)

/**
* This is the return value of a drag operation like drag_pointer.
*
* DRAGGING will indicate the drag action is still in progress and can be
* continued or resolved.
*
* DRAG_SUCCESS will indicate the intention of the drag action should be
* carried out.
*
* DRAG_REVERT will indicate an attempt should be made to restore the state of
* the involved windows to their condition before the drag.
*
* DRAG_ABORT will indicate that the intention of the drag action cannot be
* carried out (e.g. because the window has been unmapped).
*
*/
typedef enum {
DRAGGING = 0,
DRAG_SUCCESS,
DRAG_REVERT,
DRAG_ABORT
} drag_result_t;

/**
* This function grabs your pointer and keyboard and lets you drag stuff around
* (borders). Every time you move your mouse, an XCB_MOTION_NOTIFY event will
* be received and the given callback will be called with the parameters
* specified (client, the original event), the original rect of the client,
* and the new coordinates (x, y).
*
* If use_threshold is set, dragging only starts after the user moves the
* pointer past a certain threshold. That is, the cursor will not be set and the
* callback will not be called until then.
*
*/
drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event,
xcb_window_t confine_to, int cursor,
bool use_threshold, callback_t callback,
const void *extra);
45 changes: 1 addition & 44 deletions include/floating.h
Expand Up @@ -13,14 +13,6 @@

#include "tree.h"

/** Callback for dragging */
typedef void (*callback_t)(Con *, Rect *, uint32_t, uint32_t, const void *);

/** Macro to create a callback function for dragging */
#define DRAGGING_CB(name) \
static void name(Con *con, Rect *old_rect, uint32_t new_x, \
uint32_t new_y, const void *extra)

/** On which border was the dragging initiated? */
typedef enum { BORDER_LEFT = (1 << 0),
BORDER_RIGHT = (1 << 1),
Expand Down Expand Up @@ -83,7 +75,7 @@ void floating_move_to_pointer(Con *con);
* Calls the drag_pointer function with the drag_window callback
*
*/
void floating_drag_window(Con *con, const xcb_button_press_event_t *event);
void floating_drag_window(Con *con, const xcb_button_press_event_t *event, bool use_threshold);

/**
* Called when the user clicked on a floating window while holding the
Expand All @@ -106,41 +98,6 @@ void floating_resize_window(Con *con, const bool proportional, const xcb_button_
*/
void floating_check_size(Con *floating_con, bool prefer_height);

/**
* This is the return value of a drag operation like drag_pointer.
*
* DRAGGING will indicate the drag action is still in progress and can be
* continued or resolved.
*
* DRAG_SUCCESS will indicate the intention of the drag action should be
* carried out.
*
* DRAG_REVERT will indicate an attempt should be made to restore the state of
* the involved windows to their condition before the drag.
*
* DRAG_ABORT will indicate that the intention of the drag action cannot be
* carried out (e.g. because the window has been unmapped).
*
*/
typedef enum {
DRAGGING = 0,
DRAG_SUCCESS,
DRAG_REVERT,
DRAG_ABORT
} drag_result_t;

/**
* This function grabs your pointer and keyboard and lets you drag stuff around
* (borders). Every time you move your mouse, an XCB_MOTION_NOTIFY event will
* be received and the given callback will be called with the parameters
* specified (client, border on which the click originally was), the original
* rect of the client, the event and the new coordinates (x, y).
*
*/
drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event,
xcb_window_t confine_to, border_t border, int cursor,
callback_t callback, const void *extra);

/**
* Repositions the CT_FLOATING_CON to have the coordinates specified by
* newrect, but only if the coordinates are not out-of-bounds. Also reassigns
Expand Down
4 changes: 3 additions & 1 deletion include/resize.h
Expand Up @@ -13,7 +13,9 @@

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
Expand Down
57 changes: 21 additions & 36 deletions src/click.c
Expand Up @@ -26,7 +26,7 @@ typedef enum { CLICK_BORDER = 0,
* 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);
Con *second = NULL;
Con *first = con;
Expand Down Expand Up @@ -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);

resize_graphical_handler(first, second, orientation, event);
resize_graphical_handler(first, second, orientation, event, use_threshold);

DLOG("After resize handler, rendering\n");
tree_render();
Expand Down Expand Up @@ -94,22 +94,22 @@ static bool floating_mod_on_tiled_client(Con *con, xcb_button_press_event_t *eve
if (to_right < to_left &&
to_right < to_top &&
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 &&
to_left < to_top &&
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 &&
to_top < to_left &&
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 &&
to_bottom < to_left &&
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;
}
Expand All @@ -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().
*
*/
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) */
Rect bsr = con_border_style_rect(con);
DLOG("BORDER x = %d, y = %d for con %p, window 0x%08x\n",
event->event_x, event->event_y, con, event->event);
DLOG("checks for right >= %d\n", con->window_rect.x + con->window_rect.width);
if (dest == CLICK_DECORATION) {
/* The user clicked on a window decoration. We ignore the following case:
* 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);
return tiling_resize_for_border(con, BORDER_TOP, event, use_threshold);
}

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))
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) &&
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))
return tiling_resize_for_border(con, BORDER_BOTTOM, event);
return tiling_resize_for_border(con, BORDER_BOTTOM, event, false);

return false;
}
Expand Down Expand Up @@ -221,6 +202,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
Con *floatingcon = con_inside_floating(con);
const bool proportional = (event->state & XCB_KEY_BUT_MASK_SHIFT) == XCB_KEY_BUT_MASK_SHIFT;
const bool in_stacked = (con->parent->layout == L_STACKED || con->parent->layout == L_TABBED);
const bool was_focused = focused == con;

/* 1: see if the user scrolled on the decoration of a stacked/tabbed con */
if (in_stacked &&
Expand Down Expand Up @@ -258,7 +240,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
if (floatingcon != NULL && fs != con) {
/* 4: floating_modifier plus left mouse button drags */
if (mod_pressed && event->detail == XCB_BUTTON_CLICK_LEFT) {
floating_drag_window(floatingcon, event);
floating_drag_window(floatingcon, event, false);
return 1;
}

Expand All @@ -275,7 +257,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
is_left_or_right_click) {
/* try tiling resize, but continue if it doesn’t work */
DLOG("tiling resize with fallback\n");
if (tiling_resize(con, event, dest))
if (tiling_resize(con, event, dest, !was_focused))
goto done;
}

Expand All @@ -293,9 +275,8 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod

/* 6: dragging, if this was a click on a decoration (which did not lead
* to a resize) */
if (!in_stacked && dest == CLICK_DECORATION &&
(event->detail == XCB_BUTTON_CLICK_LEFT)) {
floating_drag_window(floatingcon, event);
if (dest == CLICK_DECORATION && event->detail == XCB_BUTTON_CLICK_LEFT) {
floating_drag_window(floatingcon, event, !was_focused);
return 1;
}

Expand All @@ -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) &&
is_left_or_right_click) {
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:
Expand Down
7 changes: 7 additions & 0 deletions src/commands.c
Expand Up @@ -2013,6 +2013,13 @@ void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
con_focus(previously_focused);
}

/* Let back-and-forth work after renaming the previous workspace.
* See #3694. */
if (previous_workspace_name && !strcmp(previous_workspace_name, old_name_copy)) {
FREE(previous_workspace_name);
previous_workspace_name = sstrdup(new_name);
}

cmd_output->needs_tree_render = true;
ysuccess(true);

Expand Down

0 comments on commit f9c80ac

Please sign in to comment.