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);
|
||||
|
@ -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.
|
||||
*
|
||||
@ -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.
|
||||
* Determines on which border the user clicked and launches the drag_pointer function
|
||||
* with the resize_callback.
|
||||
* 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).
|
||||
*
|
||||
*/
|
||||
int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
||||
DLOG("floating border click\n");
|
||||
|
||||
struct callback_params {
|
||||
border_t border;
|
||||
xcb_button_press_event_t *event;
|
||||
};
|
||||
|
||||
void resize_callback(Rect *old_rect, uint32_t new_x, uint32_t new_y) {
|
||||
switch (border) {
|
||||
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) ||
|
||||
@ -221,6 +224,18 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||
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)
|
||||
border = BORDER_TOP;
|
||||
else if (event->event_y >= (client->rect.height - 2))
|
||||
@ -236,21 +251,16 @@ 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;
|
||||
|
||||
/*
|
||||
* Called when the user clicked on the titlebar of a floating window.
|
||||
* Calls the drag_pointer function with the drag_window callback
|
||||
*
|
||||
*/
|
||||
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);
|
||||
@ -261,19 +271,19 @@ void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||
/* fake_absolute_configure_notify flushes */
|
||||
}
|
||||
|
||||
drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_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
|
||||
* Called when the user clicked on the titlebar of a floating window.
|
||||
* Calls the drag_pointer function with the drag_window callback
|
||||
*
|
||||
*/
|
||||
void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
||||
DLOG("floating_resize_window\n");
|
||||
void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event) {
|
||||
DLOG("floating_drag_window\n");
|
||||
|
||||
void resize_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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -288,7 +298,16 @@ void floating_resize_window(xcb_connection_t *conn, Client *client, xcb_button_p
|
||||
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,
|
||||
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:
|
||||
|
68
src/resize.c
68
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,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
|
||||
* 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),
|
||||
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