Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1412 bspwm resize #4955

Draft
wants to merge 4 commits into
base: next
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,59 @@
## PKGBUILD for Arch testing
1. Create MAKEPKG file in an empty folder
2. `makepkg -si`
```bash
# Maintainer: Jan-Erik Rediger <badboy at archlinux dot us>
# Contributor: Thorsten Toepper <atsutane at freethoughts dot de>
# Contributor: William Giokas <1007380@gmail.com>

# This PKGBUILD was prepared for pacman 4.1 by William. Thank you. :-)

pkgname=i3-cmprmsd
pkgver=4.14.r1502.g7c20b2c7
pkgrel=1
pkgdesc='An improved dynamic tiling window manager'
arch=('i686' 'x86_64')
url='http://i3wm.org/'
license=('BSD')
provides=('i3-wm')
conflicts=('i3-wm' 'i3-gaps' 'i3-gaps-next-git')
groups=('i3' 'i3-vcs')
depends=('xcb-util-keysyms' 'xcb-util-wm' 'libev' 'yajl'
'startup-notification' 'pango' 'perl' 'xcb-util-cursor' 'xcb-util-xrm'
'libxkbcommon-x11')
makedepends=('git' 'bison' 'flex' 'asciidoc' 'xmlto' 'meson')
optdepends=('i3lock: For locking your screen.'
'i3status: To display system information with a bar.')
options=('docs')
source=('git+https://github.com/cmprmsd/i3#branch=1412-bspwm-resize')
sha1sums=('SKIP')

pkgver() {
cd "$srcdir/i3"
git describe --long | sed 's/\([^-]*-g\)/r\1/;s/-/./g'
}


build() {
cd "i3"
arch-meson \
-Ddocs=true \
-Dmans=true \
../build
meson compile -C ../build
}

package() {
cd "i3"
DESTDIR="${pkgdir}" meson install -C ../build

install -Dt "${pkgdir}/usr/share/licenses/${pkgname}" -m644 LICENSE
}

# vim:set ts=2 sw=2 et:
```


![Logo](docs/logo-30.png) i3: A tiling window manager
=====================================================

Expand Down
7 changes: 0 additions & 7 deletions include/con.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,13 +469,6 @@ void con_set_layout(Con *con, layout_t layout);
*/
void con_toggle_layout(Con *con, const char *toggle_mode);

/**
* Determines the minimum size of the given con by looking at its children (for
* split/stacked/tabbed cons). Will be called when resizing floating cons
*
*/
Rect con_minimum_size(Con *con);

/**
* Returns true if changing the focus to con would be allowed considering
* the fullscreen focus constraints. Specifically, if a fullscreen container or
Expand Down
4 changes: 4 additions & 0 deletions include/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -764,4 +764,8 @@ struct Con {

/* The colormap for this con if a custom one is used. */
xcb_colormap_t colormap;

/* The minimum size of the container, which is consists of the size of the
* borders, decorations, and minimum sizes of its children. */
struct width_height min_size;
};
60 changes: 55 additions & 5 deletions include/resize.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,48 @@

#include <config.h>

typedef enum { CLICK_BORDER = 0,
CLICK_DECORATION = 1,
CLICK_INSIDE = 2 } click_destination_t;

typedef enum {
RD_NONE = 0,

RD_UP = (1 << 0),
RD_DOWN = (1 << 1),
RD_LEFT = (1 << 2),
RD_RIGHT = (1 << 3),

RD_UP_LEFT = RD_UP | RD_LEFT,
RD_UP_RIGHT = RD_UP | RD_RIGHT,
RD_DOWN_LEFT = RD_DOWN | RD_LEFT,
RD_DOWN_RIGHT = RD_DOWN | RD_RIGHT,
} resize_direction_t;

typedef struct {
Con *output;
Con *first_h;
Con *first_v;
Con *second_h;
Con *second_v;
} resize_params_t;

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,
bool use_threshold);
resize_direction_t resize_find_tiling_participants_two_axes(
Con *con, resize_direction_t dir, resize_params_t *p);

void resize_graphical_handler(const xcb_button_press_event_t *event,
enum xcursor_cursor_t cursor,
bool use_threshold,
resize_params_t *p);

/**
* Resize the two given containers using the given amount of pixels or
* percentage points. One of the two needs to be 0. A positive amount means
* growing the first container while a negative means shrinking it.
* Returns false when the resize would result in one of the two containers
* having less than 1 pixel of size.
* Return false when resize is not performed due to container minimum size
* constraints.
*
*/
bool resize_neighboring_cons(Con *first, Con *second, int px, int ppt);
Expand All @@ -33,3 +63,23 @@ bool resize_neighboring_cons(Con *first, Con *second, int px, int ppt);
*
*/
double percent_for_1px(Con *con);

/**
* Return cursor which should be used during the resize process.
*
* unidirectional_arrow should be true when it is clear from the user
* perspective which container is the main in the resizing process. In this
* case, a single-headed arrow cursor is returned. Сontrariwise, e.g. in a case
* of drag by the border between two windows, a two-headed arrow cursor is
* returned.
*
*/
enum xcursor_cursor_t xcursor_type_for_resize_direction(
resize_direction_t dir, bool unidirectional_arrow);

/**
* Return resize direction for a container based on the click coordinates and
* destination.
*
*/
resize_direction_t get_resize_direction(Con *con, int x, int y, click_destination_t dest);
5 changes: 5 additions & 0 deletions include/xcursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ enum xcursor_cursor_t {
XCURSOR_CURSOR_TOP_RIGHT_CORNER,
XCURSOR_CURSOR_BOTTOM_LEFT_CORNER,
XCURSOR_CURSOR_BOTTOM_RIGHT_CORNER,
XCURSOR_CURSOR_TOP_SIDE,
XCURSOR_CURSOR_BOTTOM_SIDE,
XCURSOR_CURSOR_LEFT_SIDE,
XCURSOR_CURSOR_RIGHT_SIDE,
XCURSOR_CURSOR_WATCH,
XCURSOR_CURSOR_MOVE,
XCURSOR_CURSOR_NOT_ALLOWED,
XCURSOR_CURSOR_MAX
};

Expand Down
135 changes: 16 additions & 119 deletions src/click.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,134 +11,33 @@

#include <time.h>

typedef enum { CLICK_BORDER = 0,
CLICK_DECORATION = 1,
CLICK_INSIDE = 2 } click_destination_t;

/*
* Finds the correct pair of first/second cons between the resize will take
* place according to the passed border position (top, left, right, bottom),
* then calls resize_graphical_handler().
*
*/
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;
direction_t search_direction;
switch (border) {
case BORDER_LEFT:
search_direction = D_LEFT;
break;
case BORDER_RIGHT:
search_direction = D_RIGHT;
break;
case BORDER_TOP:
search_direction = D_UP;
break;
case BORDER_BOTTOM:
search_direction = D_DOWN;
break;
}

bool res = resize_find_tiling_participants(&first, &second, search_direction, false);
if (!res) {
DLOG("No second container in this direction found.\n");
return false;
}
if (first->fullscreen_mode != second->fullscreen_mode) {
DLOG("Avoiding resize between containers with different fullscreen modes, %d != %d\n", first->fullscreen_mode, second->fullscreen_mode);
return false;
}

assert(first != second);
assert(first->parent == second->parent);

/* The first container should always be in front of the second container */
if (search_direction == D_UP || search_direction == D_LEFT) {
Con *tmp = first;
first = second;
second = tmp;
}

const orientation_t orientation = ((border == BORDER_LEFT || border == BORDER_RIGHT) ? HORIZ : VERT);

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

DLOG("After resize handler, rendering\n");
tree_render();
return true;
}

/*
* Called when the user clicks using the floating_modifier, but the client is in
* tiling layout.
*
* Returns false if it does not do anything (that is, the click should be sent
* to the client).
*
*/
static bool floating_mod_on_tiled_client(Con *con, xcb_button_press_event_t *event) {
/* The client is in tiling layout. We can still initiate a resize with the
* right mouse button, by chosing the border which is the most near one to
* the position of the mouse pointer */
int to_right = con->rect.width - event->event_x,
to_left = event->event_x,
to_top = event->event_y,
to_bottom = con->rect.height - event->event_y;

DLOG("click was %d px to the right, %d px to the left, %d px to top, %d px to bottom\n",
to_right, to_left, to_top, to_bottom);

if (to_right < to_left &&
to_right < to_top &&
to_right < to_bottom)
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, false);

if (to_top < to_right &&
to_top < to_left &&
to_top < to_bottom)
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, false);

return false;
static void floating_mod_on_tiled_client(Con *con, xcb_button_press_event_t *event) {
resize_direction_t dir = get_resize_direction(con, event->root_x, event->root_y, CLICK_INSIDE);
resize_params_t params;
dir = resize_find_tiling_participants_two_axes(con, dir, &params);
enum xcursor_cursor_t cursor = xcursor_type_for_resize_direction(dir, true);
resize_graphical_handler(event, cursor, false, &params);
}

/*
* 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, 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) {
return tiling_resize_for_border(con, BORDER_TOP, event, use_threshold);
static bool tiling_resize(Con *con, xcb_button_press_event_t *event, click_destination_t dest, bool use_threshold) {
resize_direction_t dir = get_resize_direction(con, event->root_x, event->root_y, dest);
resize_params_t params;
dir = resize_find_tiling_participants_two_axes(con, dir, &params);
if (dir == RD_NONE) {
return false;
}

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, 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, false);

if (event->event_y >= (int32_t)(con->window_rect.y + con->window_rect.height))
return tiling_resize_for_border(con, BORDER_BOTTOM, event, false);

return false;
enum xcursor_cursor_t cursor = xcursor_type_for_resize_direction(dir, false);
resize_graphical_handler(event, cursor, use_threshold, &params);
return true;
}

/*
Expand Down Expand Up @@ -284,9 +183,7 @@ static void route_click(Con *con, xcb_button_press_event_t *event, const bool mo

/* 7: floating modifier pressed, initiate a resize */
if (dest == CLICK_INSIDE && mod_pressed && is_right_click) {
if (floating_mod_on_tiled_client(con, event)) {
return;
}
floating_mod_on_tiled_client(con, event);
/* Avoid propagating events to clients, since the user expects
* $mod+click to be handled by i3. */
xcb_allow_events(conn, XCB_ALLOW_ASYNC_POINTER, event->time);
Expand Down