]> git.sur5r.net Git - i3/i3/commitdiff
Turn nested functions into real functions or macros
authorMichael Stapelberg <michael@stapelberg.de>
Sun, 7 Mar 2010 18:00:34 +0000 (19:00 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 7 Mar 2010 18:00:34 +0000 (19:00 +0100)
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.

common.mk
include/floating.h
src/commands.c
src/floating.c
src/resize.c

index 3b88b6fe4da29b30eb5b655dd90b2a8e1c0bcb9d..ab9c050a8ba88cc2b2b163d0a3de776360e16707 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -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}\"
index 5cf3deddc12980b849923aa15189f5b5316cac81..03da9e088f51fbf5933e1e41dd54b405105c36f3 100644 (file)
@@ -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.
  *
 #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
index a2d9ea4efe913e917dc819648c53cc820bbef02a..184394b40323e747421206df634d4e903e1119f1 100644 (file)
@@ -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);
index 02397bfc40d4d1c926b29149998372dffc9875f7..e5e8023583543751d7e83175e418d9c8f866d81f 100644 (file)
@@ -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,64 +163,79 @@ 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;
+};
+
+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;
+                }
 
-        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;
+                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;
+                }
 
-                                client->rect.y = old_rect->y + (new_y - event->root_y);
-                                client->rect.height = new_height;
-                                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;
 
-                        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;
-                        }
+                        client->rect.y = old_rect->y + (new_y - event->root_y);
+                        client->rect.height = new_height;
+                        break;
                 }
 
-                /* Push the new position/size to X11 */
-                reposition_client(conn, client);
-                resize_client(conn, client);
-                xcb_flush(conn);
+                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
+ * 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,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, &params);
 
         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);
+}
+
+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;
 
-        drag_pointer(conn, client, event, XCB_NONE, BORDER_TOP /* irrelevant */, drag_window_callback);
+        /* 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:
index 4dd0352338bbdafba24381aba1cbd55fc9cc769c..a32e57551fe26942fbf71686f0fa028d624d7e5f 100644 (file)
 #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;
-
-                        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);
-        }
+        struct callback_params params = { orientation, screen, helpwin, &new_position };
 
-        drag_pointer(conn, NULL, event, grabwin, BORDER_TOP, resize_callback);
+        drag_pointer(conn, NULL, event, grabwin, BORDER_TOP, resize_callback, &params);
 
         xcb_destroy_window(conn, helpwin);
         xcb_destroy_window(conn, grabwin);