コード例 #1
0
static void
drawin_update_drawing(drawin_t *w, int widx)
{
    luaA_object_push_item(globalconf.L, widx, w->drawable);
    drawable_set_geometry(w->drawable, -1, w->geometry);
    lua_pop(globalconf.L, 1);
}
コード例 #2
0
ファイル: luaobject.c プロジェクト: Elv13/Patched-Awesome
/** Emit a signal to an object.
 * \param L The Lua VM state.
 * \param oud The object index on the stack.
 * \param name The name of the signal.
 * \param nargs The number of arguments to pass to the called functions.
 */
void
luaA_object_emit_signal(lua_State *L, int oud,
                        const char *name, int nargs)
{
    int oud_abs = luaA_absindex(L, oud);
    lua_object_t *obj = lua_touserdata(L, oud);
    if(!obj)
        luaL_error(L, "trying to emit signal on non-object");
    signal_t *sigfound = signal_array_getbyid(&obj->signals,
                                              a_strhash((const unsigned char *) name));
    if(sigfound)
    {
        int nbfunc = sigfound->sigfuncs.len;
        luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 2, "too much signal");
        /* Push all functions and then execute, because this list can change
         * while executing funcs. */
        foreach(func, sigfound->sigfuncs)
            luaA_object_push_item(L, oud_abs, (void *) *func);

        for(int i = 0; i < nbfunc; i++)
        {
            /* push object */
            lua_pushvalue(L, oud_abs);
            /* push all args */
            for(int j = 0; j < nargs; j++)
                lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* push first function */
            lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* remove this first function */
            lua_remove(L, - nargs - nbfunc - 2 + i);
            luaA_dofunction(L, nargs + 1, 0);
        }
    }
    lua_pop(L, nargs);
}
コード例 #3
0
ファイル: drawin.c プロジェクト: nil84/awesome
static void
drawin_update_drawing(lua_State *L, int widx)
{
    drawin_t *w = luaA_checkudata(L, widx, &drawin_class);
    luaA_object_push_item(L, widx, w->drawable);
    drawable_set_geometry(L, -1, w->geometry);
    lua_pop(L, 1);
}
コード例 #4
0
ファイル: drawin.c プロジェクト: pw4ever/awesome
/** Move and/or resize a drawin
 * \param L The Lua VM state.
 * \param udx The index of the drawin.
 * \param geometry The new geometry.
 */
static void
drawin_moveresize(lua_State *L, int udx, area_t geometry)
{
    drawin_t *w = luaA_checkudata(L, udx, &drawin_class);
    int number_of_vals = 0;
    uint32_t moveresize_win_vals[4], mask_vals = 0;

    if(w->geometry.x != geometry.x)
    {
        w->geometry.x = moveresize_win_vals[number_of_vals++] = geometry.x;
        mask_vals |= XCB_CONFIG_WINDOW_X;
    }

    if(w->geometry.y != geometry.y)
    {
        w->geometry.y = moveresize_win_vals[number_of_vals++] = geometry.y;
        mask_vals |= XCB_CONFIG_WINDOW_Y;
    }

    if(geometry.width > 0 && w->geometry.width != geometry.width)
    {
        w->geometry.width = moveresize_win_vals[number_of_vals++] = geometry.width;
        mask_vals |= XCB_CONFIG_WINDOW_WIDTH;
    }

    if(geometry.height > 0 && w->geometry.height != geometry.height)
    {
        w->geometry.height = moveresize_win_vals[number_of_vals++] = geometry.height;
        mask_vals |= XCB_CONFIG_WINDOW_HEIGHT;
    }

    if(mask_vals & (XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT))
        drawin_update_drawing(w, udx);
    else {
        /* We still have to set x/y */
        luaA_object_push_item(L, udx, w->drawable);
        drawable_set_geometry(w->drawable, -1, w->geometry);
        lua_pop(L, 1);
    }

    /* Activate BMA */
    client_ignore_enterleave_events();

    if(mask_vals)
        xcb_configure_window(globalconf.connection, w->window, mask_vals, moveresize_win_vals);

    /* Deactivate BMA */
    client_restore_enterleave_events();

    if(mask_vals & XCB_CONFIG_WINDOW_X)
        luaA_object_emit_signal(L, udx, "property::x", 0);
    if(mask_vals & XCB_CONFIG_WINDOW_Y)
        luaA_object_emit_signal(L, udx, "property::y", 0);
    if(mask_vals & XCB_CONFIG_WINDOW_WIDTH)
        luaA_object_emit_signal(L, udx, "property::width", 0);
    if(mask_vals & XCB_CONFIG_WINDOW_HEIGHT)
        luaA_object_emit_signal(L, udx, "property::height", 0);
}
コード例 #5
0
ファイル: event.c プロジェクト: 8ware/awesome
/** The enter notify event handler.
 * \param ev The event.
 */
static void
event_handle_enternotify(xcb_enter_notify_event_t *ev)
{
    lua_State *L = globalconf_get_lua_State();
    client_t *c;
    drawin_t *drawin;

    globalconf.timestamp = ev->time;

    if(ev->mode != XCB_NOTIFY_MODE_NORMAL)
        return;

    if((drawin = drawin_getbywin(ev->event)))
    {
        luaA_object_push(L, drawin);
        luaA_object_push_item(L, -1, drawin->drawable);
        event_drawable_under_mouse(L, -1);
        lua_pop(L, 2);
    }

    if((c = client_getbyframewin(ev->event)))
    {
        luaA_object_push(L, c);
        /* Ignore enter with detail inferior: The pointer was previously inside
         * of a child window, so technically this isn't a 'real' enter.
         */
        if (ev->detail != XCB_NOTIFY_DETAIL_INFERIOR)
            luaA_object_emit_signal(L, -1, "mouse::enter", 0);

        drawable_t *d = client_get_drawable(c, ev->event_x, ev->event_y);
        if (d)
        {
            luaA_object_push_item(L, -1, d);
            event_drawable_under_mouse(L, -1);
            lua_pop(L, 1);
        }
        lua_pop(L, 1);
    }
    else if (ev->event == globalconf.screen->root) {
        /* When there are multiple X screens with awesome running separate
         * instances, reset focus.
         */
        globalconf.focus.need_update = true;
    }
}
コード例 #6
0
ファイル: event.c プロジェクト: 8ware/awesome
/** The motion notify event handler.
 * \param ev The event.
 */
static void
event_handle_motionnotify(xcb_motion_notify_event_t *ev)
{
    lua_State *L = globalconf_get_lua_State();
    drawin_t *w;
    client_t *c;

    globalconf.timestamp = ev->time;

    if(event_handle_mousegrabber(ev->root_x, ev->root_y, ev->state))
        return;

    if((c = client_getbyframewin(ev->event)))
    {
        luaA_object_push(L, c);
        lua_pushinteger(L, ev->event_x);
        lua_pushinteger(L, ev->event_y);
        luaA_object_emit_signal(L, -3, "mouse::move", 2);

        /* now check if a titlebar was "hit" */
        int x = ev->event_x, y = ev->event_y;
        drawable_t *d = client_get_drawable_offset(c, &x, &y);
        if (d)
        {
            luaA_object_push_item(L, -1, d);
            event_drawable_under_mouse(L, -1);
            lua_pushinteger(L, x);
            lua_pushinteger(L, y);
            luaA_object_emit_signal(L, -3, "mouse::move", 2);
            lua_pop(L, 1);
        }
        lua_pop(L, 1);
    }

    if((w = drawin_getbywin(ev->event)))
    {
        luaA_object_push(L, w);
        luaA_object_push_item(L, -1, w->drawable);
        event_drawable_under_mouse(L, -1);
        lua_pushinteger(L, ev->event_x);
        lua_pushinteger(L, ev->event_y);
        luaA_object_emit_signal(L, -3, "mouse::move", 2);
        lua_pop(L, 2);
    }
}
コード例 #7
0
ファイル: key.c プロジェクト: Asido/AwesomeWM
/** Push an array of key as an Lua table onto the stack.
 * \param L The Lua VM state.
 * \param oidx The index of the object to get items from.
 * \param keys The key array to push.
 * \return The number of elements pushed on stack.
 */
int
luaA_key_array_get(lua_State *L, int oidx, key_array_t *keys)
{
    lua_createtable(L, keys->len, 0);
    for(int i = 0; i < keys->len; i++)
    {
        luaA_object_push_item(L, oidx, keys->tab[i]);
        lua_rawseti(L, -2, i + 1);
    }
    return 1;
}
コード例 #8
0
ファイル: drawin.c プロジェクト: pw4ever/awesome
static void
drawin_update_drawing(drawin_t *w, int widx)
{
    /* If this drawin isn't visible, we don't need an up-to-date cairo surface
     * for it. (drawin_map() will later make sure we are called again) */
    if(!w->visible)
        return;

    luaA_object_push_item(globalconf.L, widx, w->drawable);
    drawable_set_geometry(w->drawable, -1, w->geometry);
    lua_pop(globalconf.L, 1);
}
コード例 #9
0
ファイル: luaobject.c プロジェクト: mengjinglei/awesome
/** Emit a signal.
 * @tparam string name A signal name.
 * @param[opt] ... Various arguments.
 * @function emit_signal
 */
void
luaA_object_emit_signal(lua_State *L, int oud,
                        const char *name, int nargs)
{
    int oud_abs = luaA_absindex(L, oud);
    lua_class_t *lua_class = luaA_class_get(L, oud);
    lua_object_t *obj = luaA_toudata(L, oud, lua_class);
    if(!obj) {
        luaA_warn(L, "Trying to emit signal '%s' on non-object", name);
        return;
    }
    else if(lua_class->checker && !lua_class->checker(obj)) {
        luaA_warn(L, "Trying to emit signal '%s' on invalid object", name);
        return;
    }
    signal_t *sigfound = signal_array_getbyid(&obj->signals,
                                              a_strhash((const unsigned char *) name));
    if(sigfound)
    {
        int nbfunc = sigfound->sigfuncs.len;
        luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 2, "too much signal");
        /* Push all functions and then execute, because this list can change
         * while executing funcs. */
        foreach(func, sigfound->sigfuncs)
            luaA_object_push_item(L, oud_abs, *func);

        for(int i = 0; i < nbfunc; i++)
        {
            /* push object */
            lua_pushvalue(L, oud_abs);
            /* push all args */
            for(int j = 0; j < nargs; j++)
                lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* push first function */
            lua_pushvalue(L, - nargs - nbfunc - 1 + i);
            /* remove this first function */
            lua_remove(L, - nargs - nbfunc - 2 + i);
            luaA_dofunction(L, nargs + 1, 0);
        }
    } else {
        luaA_warn(L, "Trying to emit unknown signal '%s'", name);
        return;
    }

    /* Then emit signal on the class */
    lua_pushvalue(L, oud);
    lua_insert(L, - nargs - 1);
    luaA_class_emit_signal(L, luaA_class_get(L, - nargs - 1), name, nargs + 1);
}
コード例 #10
0
ファイル: event.c プロジェクト: paul/awesome
/** The button press event handler.
 * \param data The type of mouse event.
 * \param connection The connection to the X server.
 * \param ev The event.
 */
static int
event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_event_t *ev)
{
    int screen;
    const int nb_screen = xcb_setup_roots_length(xcb_get_setup(connection));
    client_t *c;
    wibox_t *wibox;

    if(event_handle_mousegrabber(ev->root_x, ev->root_y, 1 << (ev->detail - 1 + 8)))
        return 0;

    /* ev->state is
     * button status (8 bits) + modifiers status (8 bits)
     * we don't care for button status that we get, especially on release, so
     * drop them */
    ev->state &= 0x00ff;

    if((wibox = wibox_getbywin(ev->event))
       || (wibox = wibox_getbywin(ev->child)))
    {
        /* If the wibox is child, then x,y are
         * relative to root window */
        if(wibox->window == ev->child)
        {
            ev->event_x -= wibox->geometry.x;
            ev->event_y -= wibox->geometry.y;
        }

        /* Push the wibox */
        luaA_object_push(globalconf.L, wibox);
        /* Duplicate the wibox */
        lua_pushvalue(globalconf.L, -1);
        /* Handle the button event on it */
        event_button_callback(ev, &wibox->buttons, -1, 1, NULL);

        /* then try to match a widget binding */
        widget_t *w = widget_getbycoords(wibox->orientation, &wibox->widgets,
                                         wibox->geometry.width,
                                         wibox->geometry.height,
                                         &ev->event_x, &ev->event_y);
        if(w)
        {
            /* Push widget (the wibox is already on stack) */
            luaA_object_push_item(globalconf.L, -1, w);
            /* Move widget before wibox */
            lua_insert(globalconf.L, -2);
            event_button_callback(ev, &w->buttons, -2, 2, NULL);
        }
        else
            /* Remove the wibox, we did not use it */
            lua_pop(globalconf.L, 1);

    }
    else if((c = client_getbywin(ev->event)))
    {
        luaA_object_push(globalconf.L, c);
        event_button_callback(ev, &c->buttons, -1, 1, NULL);
        xcb_allow_events(globalconf.connection,
                         XCB_ALLOW_REPLAY_POINTER,
                         XCB_CURRENT_TIME);
    }
    else if(ev->child == XCB_NONE)
        for(screen = 0; screen < nb_screen; screen++)
            if(xutil_screen_get(connection, screen)->root == ev->event)
            {
                event_button_callback(ev, &globalconf.buttons, 0, 0, NULL);
                return 0;
            }

    return 0;
}
コード例 #11
0
ファイル: widget.c プロジェクト: Elv13/Patched-Awesome
/** Render a list of widgets.
 * \param wibox The wibox.
 * \todo Remove GC.
 */
void
widget_render(wibox_t *wibox)
{
    lua_State *L = globalconf.L;
    draw_context_t *ctx = &wibox->ctx;
    area_t rectangle = { 0, 0, 0, 0 };
    color_t col;

    rectangle.width = ctx->width;
    rectangle.height = ctx->height;

    if (!widget_geometries(wibox))
        return;

    if(ctx->bg.alpha != 0xffff)
    {
        int x = wibox->geometry.x + wibox->border_width,
            y = wibox->geometry.y + wibox->border_width;
        xcb_get_property_reply_t *prop_r;
        char *data;
        xcb_pixmap_t rootpix;
        xcb_get_property_cookie_t prop_c;
        xcb_screen_t *s = xutil_screen_get(globalconf.connection, ctx->phys_screen);
        prop_c = xcb_get_property_unchecked(globalconf.connection, false, s->root, _XROOTPMAP_ID,
                                            PIXMAP, 0, 1);
        if((prop_r = xcb_get_property_reply(globalconf.connection, prop_c, NULL)))
        {
            if(prop_r->value_len
               && (data = xcb_get_property_value(prop_r))
               && (rootpix = *(xcb_pixmap_t *) data))
               switch(wibox->orientation)
               {
                 case North:
                   draw_rotate(ctx,
                               rootpix, ctx->pixmap,
                               s->width_in_pixels, s->height_in_pixels,
                               ctx->width, ctx->height,
                               M_PI_2,
                               y + ctx->width,
                               - x);
                   break;
                 case South:
                   draw_rotate(ctx,
                               rootpix, ctx->pixmap,
                               s->width_in_pixels, s->height_in_pixels,
                               ctx->width, ctx->height,
                               - M_PI_2,
                               - y,
                               x + ctx->height);
                   break;
                 case East:
                   xcb_copy_area(globalconf.connection, rootpix,
                                 wibox->pixmap, wibox->gc,
                                 x, y,
                                 0, 0,
                                 ctx->width, ctx->height);
                   break;
               }
            p_delete(&prop_r);
        }
    }

    widget_node_array_t *widgets = &wibox->widgets;

    widget_node_array_wipe(widgets);
    widget_node_array_init(widgets);
    /* push wibox */
    luaA_object_push(globalconf.L, wibox);
    /* push widgets table */
    luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
    /* remove wibox */
    lua_remove(globalconf.L, -2);
    luaA_table2widgets(L, widgets);

    /* get computed geometries */
    for(unsigned int i = 0; i < lua_objlen(L, -1); i++)
    {
        lua_pushnumber(L, i + 1);
        lua_gettable(L, -2);

        widgets->tab[i].geometry.x = luaA_getopt_number(L, -1, "x", wibox->geometry.x);
        widgets->tab[i].geometry.y = luaA_getopt_number(L, -1, "y", wibox->geometry.y);
        widgets->tab[i].geometry.width = luaA_getopt_number(L, -1, "width", 1);
        widgets->tab[i].geometry.height = luaA_getopt_number(L, -1, "height", 1);

        lua_pop(L, 1);
    }
    lua_pop(L, 1);

    /* draw background image, only if the background color is not opaque */
    if(wibox->bg_image && ctx->bg.alpha != 0xffff)
        draw_image(ctx, 0, 0, 1.0, wibox->bg_image);

    /* draw background color */
    xcolor_to_color(&ctx->bg, &col);
    draw_rectangle(ctx, rectangle, 1.0, true, &col);

    /* draw everything! */
    for(int i = 0; i < widgets->len; i++)
        if(widgets->tab[i].widget->isvisible)
            widgets->tab[i].widget->draw(widgets->tab[i].widget,
                                         ctx, widgets->tab[i].geometry, wibox);

    switch(wibox->orientation)
    {
        case South:
          draw_rotate(ctx, ctx->pixmap, wibox->pixmap,
                      ctx->width, ctx->height,
                      ctx->height, ctx->width,
                      M_PI_2, ctx->height, 0);
          break;
        case North:
          draw_rotate(ctx, ctx->pixmap, wibox->pixmap,
                      ctx->width, ctx->height,
                      ctx->height, ctx->width,
                      - M_PI_2, 0, ctx->width);
          break;
        case East:
          break;
    }
}
コード例 #12
0
ファイル: widget.c プロジェクト: Elv13/Patched-Awesome
/** Retrieve a list of widget geometries using a Lua layout function.
 * a table which contains the geometries is then pushed onto the stack
 * \param wibox The wibox.
 * \return True is everything is ok, false otherwise.
 */
static bool
widget_geometries(wibox_t *wibox)
{
    /* get the layout field of the widget table */
    if(wibox->widgets_table)
    {
        /* push wibox */
        luaA_object_push(globalconf.L, wibox);
        /* push widgets table */
        luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
        /* remove wibox */
        lua_remove(globalconf.L, -2);
        /* get layout field from the table */
        lua_getfield(globalconf.L, -1, "layout");
        /* remove the widget table */
        lua_remove(globalconf.L, -2);
    }
    else
        lua_pushnil(globalconf.L);

    /* if the layout field is a function */
    if(lua_isfunction(globalconf.L, -1))
    {
        /* Push 1st argument: wibox geometry */
        area_t geometry = wibox->geometry;
        geometry.x = 0;
        geometry.y = 0;
        /* we need to exchange the width and height of the wibox window if it
         * it is rotated, so the layout function doesn't need to care about that
         */
        if(wibox->orientation != East)
        {
            int i = geometry.height;
            geometry.height = geometry.width;
            geometry.width = i;
        }
        luaA_pusharea(globalconf.L, geometry);
        /* Push 2nd argument: widget table */
        luaA_object_push(globalconf.L, wibox);
        luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
        lua_remove(globalconf.L, -2);
        /* Push 3rd argument: wibox screen */
        lua_pushnumber(globalconf.L, screen_array_indexof(&globalconf.screens, wibox->screen));
        /* Re-push the layout function */
        lua_pushvalue(globalconf.L, -4);
        /* call the layout function with 3 arguments (wibox geometry, widget
         * table, screen) and wait for one result */
        if(!luaA_dofunction(globalconf.L, 3, 1))
            return false;

        /* Remove the left over layout function */
        lua_remove(globalconf.L, -2);
    }
    else
    {
        /* Remove the "nil function" */
        lua_pop(globalconf.L, 1);

        /* If no layout function has been specified, we just push a table with
         * geometries onto the stack. These geometries are nothing fancy, they
         * have x = y = 0 and their height and width set to the widgets demands
         * or the wibox size, depending on which is less.
         */

        widget_node_array_t *widgets = &wibox->widgets;
        widget_node_array_wipe(widgets);
        widget_node_array_init(widgets);

        /* push wibox */
        luaA_object_push(globalconf.L, wibox);
        /* push widgets table */
        luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
        /* remove wibox */
        lua_remove(globalconf.L, -2);
        luaA_table2widgets(globalconf.L, widgets);

        lua_newtable(globalconf.L);
        for(int i = 0; i < widgets->len; i++)
        {
            lua_pushnumber(globalconf.L, i + 1);
            widget_t *widget = widgets->tab[i].widget;
            lua_pushnumber(globalconf.L, screen_array_indexof(&globalconf.screens, wibox->screen));
            area_t geometry = widget->extents(globalconf.L, widget);
            lua_pop(globalconf.L, 1);
            geometry.x = geometry.y = 0;
            geometry.width = MIN(wibox->geometry.width, geometry.width);
            geometry.height = MIN(wibox->geometry.height, geometry.height);

            luaA_pusharea(globalconf.L, geometry);

            lua_settable(globalconf.L, -3);
        }
    }
    return true;
}
コード例 #13
0
ファイル: event.c プロジェクト: Bew78LesellB/awesome
/** The button press event handler.
 * \param ev The event.
 */
static void
event_handle_button(xcb_button_press_event_t *ev)
{
    lua_State *L = globalconf_get_lua_State();
    client_t *c;
    drawin_t *drawin;

    globalconf.timestamp = ev->time;

    {
        /* ev->state contains the state before the event. Compute the state
         * after the event for the mousegrabber.
         */
        uint16_t state = ev->state, change = 1 << (ev->detail - 1 + 8);
        if (XCB_EVENT_RESPONSE_TYPE(ev) == XCB_BUTTON_PRESS)
            state |= change;
        else
            state &= ~change;
        if(event_handle_mousegrabber(ev->root_x, ev->root_y, state))
            return;
    }

    /* ev->state is
     * button status (8 bits) + modifiers status (8 bits)
     * we don't care for button status that we get, especially on release, so
     * drop them */
    ev->state &= 0x00ff;

    if((drawin = drawin_getbywin(ev->event))
       || (drawin = drawin_getbywin(ev->child)))
    {
        /* If the drawin is child, then x,y are
         * relative to root window */
        if(drawin->window == ev->child)
        {
            ev->event_x -= drawin->geometry.x + drawin->border_width;
            ev->event_y -= drawin->geometry.y + drawin->border_width;
        }

        /* Push the drawable */
        luaA_object_push(L, drawin);
        luaA_object_push_item(L, -1, drawin->drawable);
        /* and handle the button raw button event */
        event_emit_button(L, ev);
        lua_pop(L, 1);
        /* check if any button object matches */
        event_button_callback(ev, &drawin->buttons, L, -1, 1, NULL);
        /* Either we are receiving this due to ButtonPress/Release on the root
         * window or because we grabbed the button on the window. In the later
         * case we have to call AllowEvents.
         * Use AsyncPointer instead of ReplayPointer so that the event is
         * "eaten" instead of being handled again on the root window.
         */
        if(ev->child == XCB_NONE)
            xcb_allow_events(globalconf.connection,
                             XCB_ALLOW_ASYNC_POINTER,
                             ev->time);
    }
    else if((c = client_getbyframewin(ev->event)) || (c = client_getbywin(ev->event)))
    {
        /* For clicks inside of c->window, we get two events. Once because of a
         * passive grab on c->window and then again for c->frame_window.
         * Ignore the second event (identifiable by ev->child != XCB_NONE).
         */
        if (ev->event != c->frame_window || ev->child == XCB_NONE)
        {
            luaA_object_push(L, c);
            if (c->window == ev->event)
            {
                /* Button event into the client itself (not titlebar), translate
                 * into the frame window.
                 */
                ev->event_x += c->titlebar[CLIENT_TITLEBAR_LEFT].size;
                ev->event_y += c->titlebar[CLIENT_TITLEBAR_TOP].size;
            }
            /* And handle the button raw button event */
            event_emit_button(L, ev);
            /* then check if a titlebar was "hit" */
            if (c->frame_window == ev->event)
            {
                int x = ev->event_x, y = ev->event_y;
                drawable_t *d = client_get_drawable_offset(c, &x, &y);
                if (d)
                {
                    /* Copy the event so that we can fake x/y */
                    xcb_button_press_event_t event = *ev;
                    event.event_x = x;
                    event.event_y = y;
                    luaA_object_push_item(L, -1, d);
                    event_emit_button(L, &event);
                    lua_pop(L, 1);
                }
            }
            /* then check if any button objects match */
            event_button_callback(ev, &c->buttons, L, -1, 1, NULL);
        }
        xcb_allow_events(globalconf.connection,
                         XCB_ALLOW_REPLAY_POINTER,
                         ev->time);
    }
    else if(ev->child == XCB_NONE)
        if(globalconf.screen->root == ev->event)
        {
            event_button_callback(ev, &globalconf.buttons, L, 0, 0, NULL);
            return;
        }
}