Floating resize uses arbitrary corners

This closes ticket #121
This commit is contained in:
Axel Wagner 2010-03-12 01:31:48 +01:00 committed by Michael Stapelberg
parent 4cbece46c2
commit 0f5256dc72
2 changed files with 61 additions and 12 deletions

View File

@ -21,7 +21,10 @@ typedef void(*callback_t)(xcb_connection_t*, Client*, Rect*, uint32_t, uint32_t,
void *extra)
/** On which border was the dragging initiated? */
typedef enum { BORDER_LEFT, BORDER_RIGHT, BORDER_TOP, BORDER_BOTTOM} border_t;
typedef enum { BORDER_LEFT = (1 << 0),
BORDER_RIGHT = (1 << 1),
BORDER_TOP = (1 << 2),
BORDER_BOTTOM = (1 << 3)} border_t;
/**
* Enters floating mode for the given client. Correctly takes care of the

View File

@ -169,13 +169,13 @@ void floating_assign_to_workspace(Client *client, Workspace *new_workspace) {
* extension and only on Mac OS X systems at the moment).
*
*/
struct callback_params {
struct resize_callback_params {
border_t border;
xcb_button_press_event_t *event;
};
DRAGGING_CB(resize_callback) {
struct callback_params *params = extra;
struct resize_callback_params *params = extra;
xcb_button_press_event_t *event = params->event;
switch (params->border) {
case BORDER_RIGHT: {
@ -251,7 +251,7 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
DLOG("border = %d\n", border);
struct callback_params params = { border, event };
struct resize_callback_params params = { border, event };
drag_pointer(conn, client, event, XCB_NONE, border, resize_callback, &params);
@ -282,17 +282,49 @@ void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_pre
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback, event);
}
/*
* This is an ugly data structure which we need because there is no standard
* way of having nested functions (only available as a gcc extension at the
* moment, clang doesnt support it) or blocks (only available as a clang
* extension and only on Mac OS X systems at the moment).
*
*/
struct resize_window_callback_params {
border_t corner;
xcb_button_press_event_t *event;
};
DRAGGING_CB(resize_window_callback) {
xcb_button_press_event_t *event = extra;
int32_t new_width = old_rect->width + (new_x - event->root_x);
int32_t new_height = old_rect->height + (new_y - event->root_y);
struct resize_window_callback_params *params = extra;
xcb_button_press_event_t *event = params->event;
border_t corner = params->corner;
int32_t dest_x = client->rect.x;
int32_t dest_y = client->rect.y;
uint32_t dest_width;
uint32_t dest_height;
if (corner & BORDER_LEFT) {
dest_x = old_rect->x + (new_x - event->root_x);
dest_width = old_rect->width - (new_x - event->root_x);
} else dest_width = old_rect->width + (new_x - event->root_x);
if (corner & BORDER_TOP) {
dest_y = old_rect->y + (new_y - event->root_y);
dest_height = old_rect->height - (new_y - event->root_y);
} else dest_height = old_rect->height + (new_y - event->root_y);
/* Obey minimum window size and reposition the client */
if (new_width > 0 && new_width >= client_min_width(client))
client->rect.width = new_width;
if (dest_width > 0 && dest_width >= client_min_width(client)) {
client->rect.x = dest_x;
client->rect.width = dest_width;
}
if (new_height > 0 && new_height >= client_min_height(client))
client->rect.height = new_height;
if (dest_height > 0 && dest_height >= client_min_height(client)) {
client->rect.y = dest_y;
client->rect.height = dest_height;
}
/* resize_client flushes */
resize_client(conn, client);
@ -307,7 +339,21 @@ DRAGGING_CB(resize_window_callback) {
void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
DLOG("floating_resize_window\n");
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback, event);
/* corner saves the nearest corner to the original click. It contains
* a bitmask of the nearest borders (BORDER_LEFT, BORDER_RIGHT, ) */
border_t corner = 0;
if (event->event_x <= (client->rect.width / 2))
corner |= BORDER_LEFT;
else corner |= BORDER_RIGHT;
if (event->event_y <= (client->rect.height / 2))
corner |= BORDER_TOP;
else corner |= BORDER_RIGHT;
struct resize_window_callback_params params = { corner, event };
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback, &params);
}