Example #1
0
/** The configure event handler.
 * \param ev The event.
 */
static void
event_handle_configurerequest(xcb_configure_request_event_t *ev)
{
    client_t *c;

    if((c = client_getbywin(ev->window)))
    {
        area_t geometry = c->geometry;
        uint16_t bw = c->border_width;
        uint16_t tb_left = c->titlebar[CLIENT_TITLEBAR_LEFT].size;
        uint16_t tb_right = c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
        uint16_t tb_top = c->titlebar[CLIENT_TITLEBAR_TOP].size;
        uint16_t tb_bottom = c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
        uint16_t deco_left = bw + tb_left;
        uint16_t deco_right = bw + tb_right;
        uint16_t deco_top = bw + tb_top;
        uint16_t deco_bottom = bw + tb_bottom;
        int16_t diff_w = 0, diff_h = 0, diff_border = 0;

        lua_State *L = globalconf_get_lua_State();

        if(ev->value_mask & XCB_CONFIG_WINDOW_X)
        {
            int16_t diff = 0;
            geometry.x = ev->x;
            xwindow_translate_for_gravity(c->size_hints.win_gravity, deco_left, 0, deco_right, 0, &diff, NULL);
            geometry.x += diff;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_Y)
        {
            int16_t diff = 0;
            geometry.y = ev->y;
            xwindow_translate_for_gravity(c->size_hints.win_gravity, 0, deco_top, 0, deco_bottom, NULL, &diff);
            geometry.y += diff;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_WIDTH)
        {
            uint16_t old_w = geometry.width;
            geometry.width = ev->width;
            /* The ConfigureRequest specifies the size of the client window, we want the frame */
            geometry.width += tb_left + tb_right;
            diff_w = geometry.width - old_w;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
        {
            uint16_t old_h = geometry.height;
            geometry.height = ev->height;
            /* The ConfigureRequest specifies the size of the client window, we want the frame */
            geometry.height += tb_top + tb_bottom;
            diff_h = geometry.height - old_h;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH)
        {
            diff_border = ev->border_width - bw;
            diff_h += diff_border;
            diff_w += diff_border;

            luaA_object_push(L, c);
            window_set_border_width(L, -1, ev->border_width);
            lua_pop(L, 1);
        }

        /* If the client resizes without moving itself, apply window gravity */
        if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)
        {
            int16_t diff_x = 0, diff_y = 0;
            xwindow_translate_for_gravity(c->size_hints.win_gravity, diff_border, diff_border, diff_w, diff_h, &diff_x, &diff_y);
            if(!(ev->value_mask & XCB_CONFIG_WINDOW_X))
                geometry.x += diff_x;
            if(!(ev->value_mask & XCB_CONFIG_WINDOW_Y))
                geometry.y += diff_y;
        }

        c->got_configure_request = true;

        /* Request the changes to be applied */
        luaA_object_push(L, c);
        lua_pushstring(L, "ewmh");     /* context */
        lua_newtable(L);               /* props */

        /* area, it needs to be directly in the `hints` table to comply with
           the "protocol"
         */
        lua_pushstring(L, "x");
        lua_pushinteger(L, geometry.x);
        lua_rawset(L, -3);

        lua_pushstring(L, "y");
        lua_pushinteger(L, geometry.y);
        lua_rawset(L, -3);

        lua_pushstring(L, "width");
        lua_pushinteger(L, geometry.width);
        lua_rawset(L, -3);

        lua_pushstring(L, "height");
        lua_pushinteger(L, geometry.height);
        lua_rawset(L, -3);

        luaA_object_emit_signal(L, -3, "request::geometry", 2);
        lua_pop(L, 1);
    }
    else if (xembed_getbywin(&globalconf.embedded, ev->window))
    {
        /* Ignore this so that systray icons cannot resize themselves.
         * We decide their size!
         * However, Xembed says that we act like a WM to the embedded window and
         * thus we have to send a synthetic configure notify informing the
         * window that its configure request was denied.
         */
        xcb_get_geometry_cookie_t geom_cookie =
            xcb_get_geometry_unchecked(globalconf.connection, ev->window);
        xcb_translate_coordinates_cookie_t coords_cookie =
            xcb_translate_coordinates_unchecked(globalconf.connection,
                    ev->window, globalconf.screen->root, 0, 0);
        xcb_get_geometry_reply_t *geom =
            xcb_get_geometry_reply(globalconf.connection, geom_cookie, NULL);
        xcb_translate_coordinates_reply_t *coords =
            xcb_translate_coordinates_reply(globalconf.connection, coords_cookie, NULL);

        if (geom && coords)
        {
            xwindow_configure(ev->window,
                    (area_t) { .x = coords->dst_x,
                               .y = coords->dst_y,
                               .width = geom->width,
                               .height = geom->height },
                    0);
Example #2
0
/** The configure event handler.
 * \param ev The event.
 */
static void
event_handle_configurerequest(xcb_configure_request_event_t *ev)
{
    client_t *c;

    if((c = client_getbywin(ev->window)))
    {
        area_t geometry = c->geometry;
        uint16_t bw = c->border_width;
        uint16_t tb_left = c->titlebar[CLIENT_TITLEBAR_LEFT].size;
        uint16_t tb_right = c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
        uint16_t tb_top = c->titlebar[CLIENT_TITLEBAR_TOP].size;
        uint16_t tb_bottom = c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
        uint16_t deco_left = bw + tb_left;
        uint16_t deco_right = bw + tb_right;
        uint16_t deco_top = bw + tb_top;
        uint16_t deco_bottom = bw + tb_bottom;
        int16_t diff_w = 0, diff_h = 0, diff_border = 0;

        if(ev->value_mask & XCB_CONFIG_WINDOW_X)
        {
            int16_t diff = 0;
            geometry.x = ev->x;
            xwindow_translate_for_gravity(c->size_hints.win_gravity, deco_left, 0, deco_right, 0, &diff, NULL);
            geometry.x += diff;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_Y)
        {
            int16_t diff = 0;
            geometry.y = ev->y;
            xwindow_translate_for_gravity(c->size_hints.win_gravity, 0, deco_top, 0, deco_bottom, NULL, &diff);
            geometry.y += diff;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_WIDTH)
        {
            uint16_t old_w = geometry.width;
            geometry.width = ev->width;
            /* The ConfigureRequest specifies the size of the client window, we want the frame */
            geometry.width += tb_left + tb_right;
            diff_w = geometry.width - old_w;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
        {
            uint16_t old_h = geometry.height;
            geometry.height = ev->height;
            /* The ConfigureRequest specifies the size of the client window, we want the frame */
            geometry.height += tb_top + tb_bottom;
            diff_h = geometry.height - old_h;
        }
        if(ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH)
        {
            lua_State *L = globalconf_get_lua_State();

            diff_border = ev->border_width - bw;
            diff_h += diff_border;
            diff_w += diff_border;

            luaA_object_push(L, c);
            window_set_border_width(L, -1, ev->border_width);
            lua_pop(L, 1);
        }

        /* If the client resizes without moving itself, apply window gravity */
        if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)
        {
            int16_t diff_x = 0, diff_y = 0;
            xwindow_translate_for_gravity(c->size_hints.win_gravity, diff_border, diff_border, diff_w, diff_h, &diff_x, &diff_y);
            if(!(ev->value_mask & XCB_CONFIG_WINDOW_X))
                geometry.x += diff_x;
            if(!(ev->value_mask & XCB_CONFIG_WINDOW_Y))
                geometry.y += diff_y;
        }

        if(!client_resize(c, geometry, false))
            /* ICCCM 4.1.5 / 4.2.3, if nothing was changed, send an event saying so */
            client_send_configure(c);
    }
    else if (xembed_getbywin(&globalconf.embedded, ev->window))
    {
        /* Ignore this so that systray icons cannot resize themselves.
         * We decide their size!
         */
    }
    else
        event_handle_configurerequest_configure_window(ev);
}