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 += -std=c99
|
||||||
CFLAGS += -pipe
|
CFLAGS += -pipe
|
||||||
CFLAGS += -Wall
|
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 += -Iinclude
|
||||||
CFLAGS += -I/usr/local/include
|
CFLAGS += -I/usr/local/include
|
||||||
CFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
|
CFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* i3 - an improved dynamic tiling window manager
|
* i3 - an improved dynamic tiling window manager
|
||||||
*
|
*
|
||||||
* © 2009 Michael Stapelberg and contributors
|
* © 2009-2010 Michael Stapelberg and contributors
|
||||||
*
|
*
|
||||||
* See file LICENSE for license information.
|
* See file LICENSE for license information.
|
||||||
*
|
*
|
||||||
|
@ -12,7 +12,13 @@
|
||||||
#define _FLOATING_H
|
#define _FLOATING_H
|
||||||
|
|
||||||
/** Callback for dragging */
|
/** 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? */
|
/** On which border was the dragging initiated? */
|
||||||
typedef enum { BORDER_LEFT, BORDER_RIGHT, BORDER_TOP, BORDER_BOTTOM} border_t;
|
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,
|
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
|
#endif
|
||||||
|
|
|
@ -89,12 +89,13 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
|
||||||
Workspace *t_ws = c_ws;
|
Workspace *t_ws = c_ws;
|
||||||
|
|
||||||
/* Makes sure new_col and new_row are within bounds of the new workspace */
|
/* Makes sure new_col and new_row are within bounds of the new workspace */
|
||||||
void check_colrow_boundaries() {
|
#define CHECK_COLROW_BOUNDARIES \
|
||||||
if (new_col >= t_ws->cols)
|
do { \
|
||||||
new_col = (t_ws->cols - 1);
|
if (new_col >= t_ws->cols) \
|
||||||
if (new_row >= t_ws->rows)
|
new_col = (t_ws->cols - 1); \
|
||||||
new_row = (t_ws->rows - 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 */
|
/* There always is a container. If not, current_col or current_row is wrong */
|
||||||
assert(container != NULL);
|
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);
|
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);
|
DLOG("new_col = %d, new_row = %d\n", new_col, new_row);
|
||||||
if (t_ws->table[new_col][new_row]->currently_focused == NULL) {
|
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);
|
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);
|
DLOG("new_col = %d, new_row = %d\n", new_col, new_row);
|
||||||
if (t_ws->table[new_col][new_row]->currently_focused == NULL) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_colrow_boundaries();
|
CHECK_COLROW_BOUNDARIES;
|
||||||
|
|
||||||
if (t_ws->table[new_col][new_row]->currently_focused != NULL)
|
if (t_ws->table[new_col][new_row]->currently_focused != NULL)
|
||||||
set_focus(conn, t_ws->table[new_col][new_row]->currently_focused, true);
|
set_focus(conn, t_ws->table[new_col][new_row]->currently_focused, true);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* i3 - an improved dynamic tiling window manager
|
* i3 - an improved dynamic tiling window manager
|
||||||
*
|
*
|
||||||
* © 2009 Michael Stapelberg and contributors
|
* © 2009-2010 Michael Stapelberg and contributors
|
||||||
*
|
*
|
||||||
* See file LICENSE for license information.
|
* See file LICENSE for license information.
|
||||||
*
|
*
|
||||||
|
@ -163,18 +163,21 @@ void floating_assign_to_workspace(Client *client, Workspace *new_workspace) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called whenever the user clicks on a border (not the titlebar!) of a floating window.
|
* This is an ugly data structure which we need because there is no standard
|
||||||
* Determines on which border the user clicked and launches the drag_pointer function
|
* way of having nested functions (only available as a gcc extension at the
|
||||||
* with the resize_callback.
|
* moment, clang doesn’t support it) or blocks (only available as a clang
|
||||||
|
* extension and only on Mac OS X systems at the moment).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
struct callback_params {
|
||||||
DLOG("floating border click\n");
|
|
||||||
|
|
||||||
border_t border;
|
border_t border;
|
||||||
|
xcb_button_press_event_t *event;
|
||||||
|
};
|
||||||
|
|
||||||
void resize_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
DRAGGING_CB(resize_callback) {
|
||||||
switch (border) {
|
struct callback_params *params = extra;
|
||||||
|
xcb_button_press_event_t *event = params->event;
|
||||||
|
switch (params->border) {
|
||||||
case BORDER_RIGHT: {
|
case BORDER_RIGHT: {
|
||||||
int new_width = old_rect->width + (new_x - event->root_x);
|
int new_width = old_rect->width + (new_x - event->root_x);
|
||||||
if ((new_width < 0) ||
|
if ((new_width < 0) ||
|
||||||
|
@ -219,7 +222,19 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||||
reposition_client(conn, client);
|
reposition_client(conn, client);
|
||||||
resize_client(conn, client);
|
resize_client(conn, client);
|
||||||
xcb_flush(conn);
|
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
|
||||||
|
* with the resize_callback.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
||||||
|
DLOG("floating border click\n");
|
||||||
|
|
||||||
|
border_t border;
|
||||||
|
|
||||||
if (event->event_y < 2)
|
if (event->event_y < 2)
|
||||||
border = BORDER_TOP;
|
border = BORDER_TOP;
|
||||||
|
@ -236,11 +251,25 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||||
|
|
||||||
DLOG("border = %d\n", border);
|
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;
|
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.
|
* Called when the user clicked on the titlebar of a floating window.
|
||||||
|
@ -250,30 +279,11 @@ 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) {
|
void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
||||||
DLOG("floating_drag_window\n");
|
DLOG("floating_drag_window\n");
|
||||||
|
|
||||||
void drag_window_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback, event);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
DRAGGING_CB(resize_window_callback) {
|
||||||
* Called when the user right-clicked on the titlebar of a floating window to
|
xcb_button_press_event_t *event = extra;
|
||||||
* resize it.
|
|
||||||
* Calls the drag_pointer function with the resize_window callback
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
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_width = old_rect->width + (new_x - event->root_x);
|
||||||
int32_t new_height = old_rect->height + (new_y - event->root_y);
|
int32_t new_height = old_rect->height + (new_y - event->root_y);
|
||||||
|
|
||||||
|
@ -286,9 +296,18 @@ void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_p
|
||||||
|
|
||||||
/* resize_client flushes */
|
/* resize_client flushes */
|
||||||
resize_client(conn, client);
|
resize_client(conn, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, resize_window_callback);
|
/*
|
||||||
|
* Called when the user right-clicked on the titlebar of a floating window to
|
||||||
|
* resize it.
|
||||||
|
* Calls the drag_pointer function with the 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
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;
|
xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(conn)).data->root;
|
||||||
uint32_t new_x, new_y;
|
uint32_t new_x, new_y;
|
||||||
Rect old_rect;
|
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_x = ((xcb_motion_notify_event_t*)last_motion_notify)->root_x;
|
||||||
new_y = ((xcb_motion_notify_event_t*)last_motion_notify)->root_y;
|
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);
|
FREE(last_motion_notify);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
|
68
src/resize.c
68
src/resize.c
|
@ -30,6 +30,44 @@
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "log.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
|
* Renders the resize window between the first/second container and resizes
|
||||||
* the table column/row.
|
* the table column/row.
|
||||||
|
@ -37,8 +75,8 @@
|
||||||
*/
|
*/
|
||||||
int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, int second,
|
int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, int second,
|
||||||
resize_orientation_t orientation, xcb_button_press_event_t *event) {
|
resize_orientation_t orientation, xcb_button_press_event_t *event) {
|
||||||
int new_position;
|
uint32_t new_position;
|
||||||
struct xoutput *screen = get_output_containing(event->root_x, event->root_y);
|
Output *screen = get_output_containing(event->root_x, event->root_y);
|
||||||
if (screen == NULL) {
|
if (screen == NULL) {
|
||||||
ELOG("BUG: No screen found at this position (%d, %d)\n", event->root_x, event->root_y);
|
ELOG("BUG: No screen found at this position (%d, %d)\n", event->root_x, event->root_y);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -49,7 +87,7 @@ 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
|
* screens during runtime. Instead, we just use the most right and most
|
||||||
* bottom Xinerama screen and use their position + width/height to get
|
* bottom Xinerama screen and use their position + width/height to get
|
||||||
* the area of pixels currently in use */
|
* the area of pixels currently in use */
|
||||||
struct xoutput *most_right = get_output_most(D_RIGHT, screen),
|
Output *most_right = get_output_most(D_RIGHT, screen),
|
||||||
*most_bottom = get_output_most(D_DOWN, 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);
|
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);
|
xcb_flush(conn);
|
||||||
|
|
||||||
void resize_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
struct callback_params params = { orientation, screen, helpwin, &new_position };
|
||||||
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;
|
|
||||||
|
|
||||||
values[0] = new_position = new_x;
|
drag_pointer(conn, NULL, event, grabwin, BORDER_TOP, resize_callback, ¶ms);
|
||||||
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);
|
|
||||||
|
|
||||||
xcb_destroy_window(conn, helpwin);
|
xcb_destroy_window(conn, helpwin);
|
||||||
xcb_destroy_window(conn, grabwin);
|
xcb_destroy_window(conn, grabwin);
|
||||||
|
|
Loading…
Reference in New Issue