Turn nested functions into real functions or macros
This enables compilation with llvm-clang and thus closes ticket #101. While it makes the code more ugly, I don’t see a beautiful solution which would enable us to stay with the more elegant solution of nested functions and still allow compilation with any other compiler than gcc.
This commit is contained in:
parent
f66d018e02
commit
85308715ea
@ -7,7 +7,9 @@ VERSION:=$(shell git describe --tags --abbrev=0)
|
||||
CFLAGS += -std=c99
|
||||
CFLAGS += -pipe
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wunused
|
||||
# unused-function, unused-label, unused-variable are turned on by -Wall
|
||||
# We don’t want unused-parameter because of the use of many callbacks
|
||||
CFLAGS += -Wunused-value
|
||||
CFLAGS += -Iinclude
|
||||
CFLAGS += -I/usr/local/include
|
||||
CFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
*
|
||||
* © 2009 Michael Stapelberg and contributors
|
||||
* © 2009-2010 Michael Stapelberg and contributors
|
||||
*
|
||||
* See file LICENSE for license information.
|
||||
*
|
||||
@ -12,7 +12,13 @@
|
||||
#define _FLOATING_H
|
||||
|
||||
/** Callback for dragging */
|
||||
typedef void(*callback_t)(Rect*, uint32_t, uint32_t);
|
||||
typedef void(*callback_t)(xcb_connection_t*, Client*, Rect*, uint32_t, uint32_t, void*);
|
||||
|
||||
/** Macro to create a callback function for dragging */
|
||||
#define DRAGGING_CB(name) \
|
||||
static void name(xcb_connection_t *conn, Client *client, \
|
||||
Rect *old_rect, uint32_t new_x, uint32_t new_y, \
|
||||
void *extra)
|
||||
|
||||
/** On which border was the dragging initiated? */
|
||||
typedef enum { BORDER_LEFT, BORDER_RIGHT, BORDER_TOP, BORDER_BOTTOM} border_t;
|
||||
@ -97,6 +103,7 @@ void floating_toggle_hide(xcb_connection_t *conn, Workspace *workspace);
|
||||
*
|
||||
*/
|
||||
void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event,
|
||||
xcb_window_t confine_to, border_t border, callback_t callback);
|
||||
xcb_window_t confine_to, border_t border, callback_t callback,
|
||||
void *extra);
|
||||
|
||||
#endif
|
||||
|
@ -89,12 +89,13 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
|
||||
Workspace *t_ws = c_ws;
|
||||
|
||||
/* Makes sure new_col and new_row are within bounds of the new workspace */
|
||||
void check_colrow_boundaries() {
|
||||
if (new_col >= t_ws->cols)
|
||||
new_col = (t_ws->cols - 1);
|
||||
if (new_row >= t_ws->rows)
|
||||
new_row = (t_ws->rows - 1);
|
||||
}
|
||||
#define CHECK_COLROW_BOUNDARIES \
|
||||
do { \
|
||||
if (new_col >= t_ws->cols) \
|
||||
new_col = (t_ws->cols - 1); \
|
||||
if (new_row >= t_ws->rows) \
|
||||
new_row = (t_ws->rows - 1); \
|
||||
} while (0)
|
||||
|
||||
/* There always is a container. If not, current_col or current_row is wrong */
|
||||
assert(container != NULL);
|
||||
@ -174,7 +175,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
|
||||
new_row = (direction == D_UP ? (t_ws->rows - 1) : 0);
|
||||
}
|
||||
|
||||
check_colrow_boundaries();
|
||||
CHECK_COLROW_BOUNDARIES;
|
||||
|
||||
DLOG("new_col = %d, new_row = %d\n", new_col, new_row);
|
||||
if (t_ws->table[new_col][new_row]->currently_focused == NULL) {
|
||||
@ -216,7 +217,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
|
||||
new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0);
|
||||
}
|
||||
|
||||
check_colrow_boundaries();
|
||||
CHECK_COLROW_BOUNDARIES;
|
||||
|
||||
DLOG("new_col = %d, new_row = %d\n", new_col, new_row);
|
||||
if (t_ws->table[new_col][new_row]->currently_focused == NULL) {
|
||||
@ -235,7 +236,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
|
||||
return;
|
||||
}
|
||||
|
||||
check_colrow_boundaries();
|
||||
CHECK_COLROW_BOUNDARIES;
|
||||
|
||||
if (t_ws->table[new_col][new_row]->currently_focused != NULL)
|
||||
set_focus(conn, t_ws->table[new_col][new_row]->currently_focused, true);
|
||||
|
177
src/floating.c
177
src/floating.c
@ -3,7 +3,7 @@
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
*
|
||||
* © 2009 Michael Stapelberg and contributors
|
||||
* © 2009-2010 Michael Stapelberg and contributors
|
||||
*
|
||||
* See file LICENSE for license information.
|
||||
*
|
||||
@ -162,6 +162,69 @@ void floating_assign_to_workspace(Client *client, Workspace *new_workspace) {
|
||||
client->workspace->fullscreen_client = client;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 doesn’t support it) or blocks (only available as a clang
|
||||
* extension and only on Mac OS X systems at the moment).
|
||||
*
|
||||
*/
|
||||
struct callback_params {
|
||||
border_t border;
|
||||
xcb_button_press_event_t *event;
|
||||
};
|
||||
|
||||
DRAGGING_CB(resize_callback) {
|
||||
struct callback_params *params = extra;
|
||||
xcb_button_press_event_t *event = params->event;
|
||||
switch (params->border) {
|
||||
case BORDER_RIGHT: {
|
||||
int new_width = old_rect->width + (new_x - event->root_x);
|
||||
if ((new_width < 0) ||
|
||||
(new_width < client_min_width(client) && client->rect.width >= new_width))
|
||||
return;
|
||||
client->rect.width = new_width;
|
||||
break;
|
||||
}
|
||||
|
||||
case BORDER_BOTTOM: {
|
||||
int new_height = old_rect->height + (new_y - event->root_y);
|
||||
if ((new_height < 0) ||
|
||||
(new_height < client_min_height(client) && client->rect.height >= new_height))
|
||||
return;
|
||||
client->rect.height = old_rect->height + (new_y - event->root_y);
|
||||
break;
|
||||
}
|
||||
|
||||
case BORDER_TOP: {
|
||||
int new_height = old_rect->height + (event->root_y - new_y);
|
||||
if ((new_height < 0) ||
|
||||
(new_height < client_min_height(client) && client->rect.height >= new_height))
|
||||
return;
|
||||
|
||||
client->rect.y = old_rect->y + (new_y - event->root_y);
|
||||
client->rect.height = new_height;
|
||||
break;
|
||||
}
|
||||
|
||||
case BORDER_LEFT: {
|
||||
int new_width = old_rect->width + (event->root_x - new_x);
|
||||
if ((new_width < 0) ||
|
||||
(new_width < client_min_width(client) && client->rect.width >= new_width))
|
||||
return;
|
||||
client->rect.x = old_rect->x + (new_x - event->root_x);
|
||||
client->rect.width = new_width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Push the new position/size to X11 */
|
||||
reposition_client(conn, client);
|
||||
resize_client(conn, client);
|
||||
xcb_flush(conn);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called whenever the user clicks on a border (not the titlebar!) of a floating window.
|
||||
* Determines on which border the user clicked and launches the drag_pointer function
|
||||
@ -173,54 +236,6 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||
|
||||
border_t border;
|
||||
|
||||
void resize_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
||||
switch (border) {
|
||||
case BORDER_RIGHT: {
|
||||
int new_width = old_rect->width + (new_x - event->root_x);
|
||||
if ((new_width < 0) ||
|
||||
(new_width < client_min_width(client) && client->rect.width >= new_width))
|
||||
return;
|
||||
client->rect.width = new_width;
|
||||
break;
|
||||
}
|
||||
|
||||
case BORDER_BOTTOM: {
|
||||
int new_height = old_rect->height + (new_y - event->root_y);
|
||||
if ((new_height < 0) ||
|
||||
(new_height < client_min_height(client) && client->rect.height >= new_height))
|
||||
return;
|
||||
client->rect.height = old_rect->height + (new_y - event->root_y);
|
||||
break;
|
||||
}
|
||||
|
||||
case BORDER_TOP: {
|
||||
int new_height = old_rect->height + (event->root_y - new_y);
|
||||
if ((new_height < 0) ||
|
||||
(new_height < client_min_height(client) && client->rect.height >= new_height))
|
||||
return;
|
||||
|
||||
client->rect.y = old_rect->y + (new_y - event->root_y);
|
||||
client->rect.height = new_height;
|
||||
break;
|
||||
}
|
||||
|
||||
case BORDER_LEFT: {
|
||||
int new_width = old_rect->width + (event->root_x - new_x);
|
||||
if ((new_width < 0) ||
|
||||
(new_width < client_min_width(client) && client->rect.width >= new_width))
|
||||
return;
|
||||
client->rect.x = old_rect->x + (new_x - event->root_x);
|
||||
client->rect.width = new_width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Push the new position/size to X11 */
|
||||
reposition_client(conn, client);
|
||||
resize_client(conn, client);
|
||||
xcb_flush(conn);
|
||||
}
|
||||
|
||||
if (event->event_y < 2)
|
||||
border = BORDER_TOP;
|
||||
else if (event->event_y >= (client->rect.height - 2))
|
||||
@ -236,11 +251,25 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||
|
||||
DLOG("border = %d\n", border);
|
||||
|
||||
drag_pointer(conn, client, event, XCB_NONE, border, resize_callback);
|
||||
struct callback_params params = { border, event };
|
||||
|
||||
drag_pointer(conn, client, event, XCB_NONE, border, resize_callback, ¶ms);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
DRAGGING_CB(drag_window_callback) {
|
||||
struct xcb_button_press_event_t *event = extra;
|
||||
|
||||
/* Reposition the client correctly while moving */
|
||||
client->rect.x = old_rect->x + (new_x - event->root_x);
|
||||
client->rect.y = old_rect->y + (new_y - event->root_y);
|
||||
reposition_client(conn, client);
|
||||
/* Because reposition_client does not send a faked configure event (only resize does),
|
||||
* we need to initiate that on our own */
|
||||
fake_absolute_configure_notify(conn, client);
|
||||
/* fake_absolute_configure_notify flushes */
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the user clicked on the titlebar of a floating window.
|
||||
@ -250,18 +279,23 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||
void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
||||
DLOG("floating_drag_window\n");
|
||||
|
||||
void drag_window_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
||||
/* Reposition the client correctly while moving */
|
||||
client->rect.x = old_rect->x + (new_x - event->root_x);
|
||||
client->rect.y = old_rect->y + (new_y - event->root_y);
|
||||
reposition_client(conn, client);
|
||||
/* Because reposition_client does not send a faked configure event (only resize does),
|
||||
* we need to initiate that on our own */
|
||||
fake_absolute_configure_notify(conn, client);
|
||||
/* fake_absolute_configure_notify flushes */
|
||||
}
|
||||
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback, event);
|
||||
}
|
||||
|
||||
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback);
|
||||
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);
|
||||
|
||||
/* Obey minimum window size and reposition the client */
|
||||
if (new_width > 0 && new_width >= client_min_width(client))
|
||||
client->rect.width = new_width;
|
||||
|
||||
if (new_height > 0 && new_height >= client_min_height(client))
|
||||
client->rect.height = new_height;
|
||||
|
||||
/* resize_client flushes */
|
||||
resize_client(conn, client);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -273,22 +307,7 @@ void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||
void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
||||
DLOG("floating_resize_window\n");
|
||||
|
||||
void resize_window_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
||||
int32_t new_width = old_rect->width + (new_x - event->root_x);
|
||||
int32_t new_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 (new_height > 0 && new_height >= client_min_height(client))
|
||||
client->rect.height = new_height;
|
||||
|
||||
/* resize_client flushes */
|
||||
resize_client(conn, client);
|
||||
}
|
||||
|
||||
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback);
|
||||
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback, event);
|
||||
}
|
||||
|
||||
|
||||
@ -301,7 +320,7 @@ void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_p
|
||||
*
|
||||
*/
|
||||
void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event,
|
||||
xcb_window_t confine_to, border_t border, callback_t callback) {
|
||||
xcb_window_t confine_to, border_t border, callback_t callback, void *extra) {
|
||||
xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(conn)).data->root;
|
||||
uint32_t new_x, new_y;
|
||||
Rect old_rect;
|
||||
@ -371,7 +390,7 @@ void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_press_event
|
||||
new_x = ((xcb_motion_notify_event_t*)last_motion_notify)->root_x;
|
||||
new_y = ((xcb_motion_notify_event_t*)last_motion_notify)->root_y;
|
||||
|
||||
callback(&old_rect, new_x, new_y);
|
||||
callback(conn, client, &old_rect, new_x, new_y, extra);
|
||||
FREE(last_motion_notify);
|
||||
}
|
||||
done:
|
||||
|
70
src/resize.c
70
src/resize.c
@ -30,6 +30,44 @@
|
||||
#include "workspace.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
* 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 doesn’t support it) or blocks (only available as a clang
|
||||
* extension and only on Mac OS X systems at the moment).
|
||||
*
|
||||
*/
|
||||
struct callback_params {
|
||||
resize_orientation_t orientation;
|
||||
Output *screen;
|
||||
xcb_window_t helpwin;
|
||||
uint32_t *new_position;
|
||||
};
|
||||
|
||||
DRAGGING_CB(resize_callback) {
|
||||
struct callback_params *params = extra;
|
||||
Output *screen = params->screen;
|
||||
DLOG("new x = %d, y = %d\n", new_x, new_y);
|
||||
if (params->orientation == O_VERTICAL) {
|
||||
/* Check if the new coordinates are within screen boundaries */
|
||||
if (new_x > (screen->rect.x + screen->rect.width - 25) ||
|
||||
new_x < (screen->rect.x + 25))
|
||||
return;
|
||||
|
||||
*(params->new_position) = new_x;
|
||||
xcb_configure_window(conn, params->helpwin, XCB_CONFIG_WINDOW_X, params->new_position);
|
||||
} else {
|
||||
if (new_y > (screen->rect.y + screen->rect.height - 25) ||
|
||||
new_y < (screen->rect.y + 25))
|
||||
return;
|
||||
|
||||
*(params->new_position) = new_y;
|
||||
xcb_configure_window(conn, params->helpwin, XCB_CONFIG_WINDOW_Y, params->new_position);
|
||||
}
|
||||
|
||||
xcb_flush(conn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Renders the resize window between the first/second container and resizes
|
||||
* the table column/row.
|
||||
@ -37,8 +75,8 @@
|
||||
*/
|
||||
int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, int second,
|
||||
resize_orientation_t orientation, xcb_button_press_event_t *event) {
|
||||
int new_position;
|
||||
struct xoutput *screen = get_output_containing(event->root_x, event->root_y);
|
||||
uint32_t new_position;
|
||||
Output *screen = get_output_containing(event->root_x, event->root_y);
|
||||
if (screen == NULL) {
|
||||
ELOG("BUG: No screen found at this position (%d, %d)\n", event->root_x, event->root_y);
|
||||
return 1;
|
||||
@ -49,8 +87,8 @@ int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, i
|
||||
* screens during runtime. Instead, we just use the most right and most
|
||||
* bottom Xinerama screen and use their position + width/height to get
|
||||
* the area of pixels currently in use */
|
||||
struct xoutput *most_right = get_output_most(D_RIGHT, screen),
|
||||
*most_bottom = get_output_most(D_DOWN, screen);
|
||||
Output *most_right = get_output_most(D_RIGHT, screen),
|
||||
*most_bottom = get_output_most(D_DOWN, screen);
|
||||
|
||||
DLOG("event->event_x = %d, event->root_x = %d\n", event->event_x, event->root_x);
|
||||
|
||||
@ -100,29 +138,9 @@ int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, i
|
||||
|
||||
xcb_flush(conn);
|
||||
|
||||
void resize_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
||||
DLOG("new x = %d, y = %d\n", new_x, new_y);
|
||||
if (orientation == O_VERTICAL) {
|
||||
/* Check if the new coordinates are within screen boundaries */
|
||||
if (new_x > (screen->rect.x + screen->rect.width - 25) ||
|
||||
new_x < (screen->rect.x + 25))
|
||||
return;
|
||||
struct callback_params params = { orientation, screen, helpwin, &new_position };
|
||||
|
||||
values[0] = new_position = new_x;
|
||||
xcb_configure_window(conn, helpwin, XCB_CONFIG_WINDOW_X, values);
|
||||
} else {
|
||||
if (new_y > (screen->rect.y + screen->rect.height - 25) ||
|
||||
new_y < (screen->rect.y + 25))
|
||||
return;
|
||||
|
||||
values[0] = new_position = new_y;
|
||||
xcb_configure_window(conn, helpwin, XCB_CONFIG_WINDOW_Y, values);
|
||||
}
|
||||
|
||||
xcb_flush(conn);
|
||||
}
|
||||
|
||||
drag_pointer(conn, NULL, event, grabwin, BORDER_TOP, resize_callback);
|
||||
drag_pointer(conn, NULL, event, grabwin, BORDER_TOP, resize_callback, ¶ms);
|
||||
|
||||
xcb_destroy_window(conn, helpwin);
|
||||
xcb_destroy_window(conn, grabwin);
|
||||
|
Loading…
Reference in New Issue
Block a user