示例#1
0
文件: drawable.c 项目: nil84/awesome
void
drawable_set_geometry(lua_State *L, int didx, area_t geom)
{
    drawable_t *d = luaA_checkudata(L, didx, &drawable_class);
    area_t old = d->geometry;
    d->geometry = geom;

    bool size_changed = (old.width != geom.width) || (old.height != geom.height);
    if (size_changed)
        drawable_unset_surface(d);
    if (size_changed && geom.width > 0 && geom.height > 0)
    {
        d->pixmap = xcb_generate_id(globalconf.connection);
        xcb_create_pixmap(globalconf.connection, globalconf.default_depth, d->pixmap,
                          globalconf.screen->root, geom.width, geom.height);
        d->surface = cairo_xcb_surface_create(globalconf.connection,
                                              d->pixmap, globalconf.visual,
                                              geom.width, geom.height);
        luaA_object_emit_signal(L, didx, "property::surface", 0);
    }

    if (old.x != geom.x)
        luaA_object_emit_signal(L, didx, "property::x", 0);
    if (old.y != geom.y)
        luaA_object_emit_signal(L, didx, "property::y", 0);
    if (old.width != geom.width)
        luaA_object_emit_signal(L, didx, "property::width", 0);
    if (old.height != geom.height)
        luaA_object_emit_signal(L, didx, "property::height", 0);
}
示例#2
0
文件: event.c 项目: 8ware/awesome
/** Record that the given drawable contains the pointer.
 */
void
event_drawable_under_mouse(lua_State *L, int ud)
{
    void *d;

    lua_pushvalue(L, ud);
    d = luaA_object_ref(L, -1);

    if (d == globalconf.drawable_under_mouse)
    {
        /* Nothing to do */
        luaA_object_unref(L, d);
        return;
    }

    if (globalconf.drawable_under_mouse != NULL)
    {
        /* Emit leave on previous drawable */
        luaA_object_push(L, globalconf.drawable_under_mouse);
        luaA_object_emit_signal(L, -1, "mouse::leave", 0);
        lua_pop(L, 1);

        /* Unref the previous drawable */
        luaA_object_unref(L, globalconf.drawable_under_mouse);
        globalconf.drawable_under_mouse = NULL;
    }
    if (d != NULL)
    {
        /* Reference the drawable for leave event later */
        globalconf.drawable_under_mouse = d;

        /* Emit enter */
        luaA_object_emit_signal(L, ud, "mouse::enter", 0);
    }
}
示例#3
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);
}
示例#4
0
文件: event.c 项目: 8ware/awesome
/** The shape notify event handler.
 * \param ev The event.
 */
static void
event_handle_shape_notify(xcb_shape_notify_event_t *ev)
{
    client_t *c = client_getbywin(ev->affected_window);
    if (c)
    {
        lua_State *L = globalconf_get_lua_State();
        luaA_object_push(L, c);
        if (ev->shape_kind == XCB_SHAPE_SK_BOUNDING)
            luaA_object_emit_signal(L, -1, "property::shape_client_bounding", 0);
        if (ev->shape_kind == XCB_SHAPE_SK_CLIP)
            luaA_object_emit_signal(L, -1, "property::shape_client_clip", 0);
        lua_pop(L, 1);
    }
}
示例#5
0
static void
tag_client_emit_signal(lua_State *L, tag_t *t, client_t *c, const char *signame)
{
    luaA_object_push(L, c);
    luaA_object_push(L, t);
    /* emit signal on client, with new tag as argument */
    luaA_object_emit_signal(L, -2, signame, 1);
    /* re push tag */
    luaA_object_push(L, t);
    /* move tag before client */
    lua_insert(L, -2);
    luaA_object_emit_signal(L, -2, signame, 1);
    /* Remove tag */
    lua_pop(L, 1);
}
示例#6
0
文件: button.c 项目: raedwulf/awesome
static int
luaA_button_set_modifiers(lua_State *L, button_t *b)
{
    b->modifiers = luaA_tomodifiers(L, -1);
    luaA_object_emit_signal(L, -3, "property::modifiers", 0);
    return 0;
}
示例#7
0
文件: button.c 项目: raedwulf/awesome
static int
luaA_button_set_button(lua_State *L, button_t *b)
{
    b->button = luaL_checknumber(L, -1);
    luaA_object_emit_signal(L, -3, "property::button", 0);
    return 0;
}
示例#8
0
文件: event.c 项目: 8ware/awesome
/** The leave notify event handler.
 * \param ev The event.
 */
static void
event_handle_leavenotify(xcb_leave_notify_event_t *ev)
{
    lua_State *L = globalconf_get_lua_State();
    client_t *c;

    globalconf.timestamp = ev->time;

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

    /* Ignore leave with detail inferior (we were left for a window contained in
     * our window, so technically the pointer is still inside of this window).
     */
    if(ev->detail != XCB_NOTIFY_DETAIL_INFERIOR && (c = client_getbyframewin(ev->event)))
    {
        luaA_object_push(L, c);
        luaA_object_emit_signal(L, -1, "mouse::leave", 0);
        lua_pop(L, 1);
    }

    lua_pushnil(L);
    event_drawable_under_mouse(L, -1);
    lua_pop(L, 1);
}
示例#9
0
/** View or unview a tag.
 * \param L The Lua VM state.
 * \param udx The index of the tag on the stack.
 * \param view Set visible or not.
 */
static void
tag_view(lua_State *L, int udx, bool view)
{
    tag_t *tag = luaA_checkudata(L, udx, &tag_class);
    if(tag->selected != view)
    {
        tag->selected = view;

        if(tag->screen)
        {
            int screen_index = screen_array_indexof(&globalconf.screens, tag->screen);

            banning_need_update(tag->screen);

            ewmh_update_net_current_desktop(screen_virttophys(screen_index));

            if(globalconf.hooks.tags != LUA_REFNIL)
            {
                lua_pushnumber(globalconf.L, screen_index + 1);
                luaA_object_push(globalconf.L, tag);
                if(view)
                    lua_pushliteral(globalconf.L, "select");
                else
                    lua_pushliteral(globalconf.L, "unselect");
                luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.tags, 3, 0);
            }
        }

        luaA_object_emit_signal(L, udx, "property::selected", 0);
    }
}
示例#10
0
文件: key.c 项目: Asido/AwesomeWM
static int
luaA_key_set_modifiers(lua_State *L, keyb_t *k)
{
    k->modifiers = luaA_tomodifiers(L, -1);
    luaA_object_emit_signal(L, -3, "property::modifiers", 0);
    return 0;
}
示例#11
0
文件: key.c 项目: Asido/AwesomeWM
static void
luaA_keystore(lua_State *L, int ud, const char *str, ssize_t len)
{
    keyb_t *key = luaA_checkudata(L, ud, &key_class);
    if(len)
    {
        if(*str != '#')
        {
            key->keysym = XStringToKeysym(str);
            if(!key->keysym)
            {
                if(len == 1)
                    key->keysym = *str;
                else
                    warn("there's no keysym named \"%s\"", str);
            }
            key->keycode = 0;
        }
        else
        {
            key->keycode = atoi(str + 1);
            key->keysym = 0;
        }
        luaA_object_emit_signal(L, ud, "property::key", 0);
    }
}
示例#12
0
文件: timer.c 项目: GinoM/awesome
static int
luaA_timer_set_timeout(lua_State *L, atimer_t *timer)
{
    double timeout = luaL_checknumber(L, -1);
    timer->timeout = timeout;
    luaA_object_emit_signal(L, -3, "property::timeout", 0);
    return 0;
}
示例#13
0
文件: timer.c 项目: GinoM/awesome
static gboolean
timer_emit_signal(gpointer data)
{
    luaA_object_push(globalconf.L, data);
    luaA_object_emit_signal(globalconf.L, -1, "timeout", 0);
    lua_pop(globalconf.L, 1);
    return TRUE;
}
示例#14
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);
    }
}
示例#15
0
文件: window.c 项目: Asido/AwesomeWM
/** Set a window opacity.
 * \param L The Lua VM state.
 * \param idx The index of the window on the stack.
 * \param opacity The opacity value.
 */
void
window_set_opacity(lua_State *L, int idx, double opacity)
{
    window_t *window = luaA_checkudata(L, idx, &window_class);

    if(window->opacity != opacity)
    {
        window->opacity = opacity;
        xwindow_set_opacity(window_get(window), opacity);
        luaA_object_emit_signal(L, idx, "property::opacity", 0);
    }
}
示例#16
0
文件: tag.c 项目: 8ware/awesome
/** View or unview a tag.
 * \param L The Lua VM state.
 * \param udx The index of the tag on the stack.
 * \param view Set selected or not.
 */
static void
tag_view(lua_State *L, int udx, bool view)
{
    tag_t *tag = luaA_checkudata(L, udx, &tag_class);
    if(tag->selected != view)
    {
        tag->selected = view;
        banning_need_update();
        ewmh_update_net_current_desktop();

        luaA_object_emit_signal(L, udx, "property::selected", 0);
    }
}
示例#17
0
文件: window.c 项目: Asido/AwesomeWM
/** Get or set mouse buttons bindings on a window.
 * \param L The Lua VM state.
 * \return The number of elements pushed on the stack.
 */
static int
luaA_window_buttons(lua_State *L)
{
    window_t *window = luaA_checkudata(L, 1, &window_class);

    if(lua_gettop(L) == 2)
    {
        luaA_button_array_set(L, 1, 2, &window->buttons);
        luaA_object_emit_signal(L, 1, "property::buttons", 0);
        xwindow_buttons_grab(window_get(window), &window->buttons);
    }

    return luaA_button_array_get(L, 1, &window->buttons);
}
示例#18
0
文件: window.c 项目: Asido/AwesomeWM
/** Set the window type.
 * \param L The Lua VM state.
 * \param window The window object.
 * \return The number of elements pushed on stack.
 */
int
luaA_window_set_type(lua_State *L, window_t *w)
{
    window_type_t type;
    const char *buf = luaL_checkstring(L, -1);

    if (A_STREQ(buf, "desktop"))
        type = WINDOW_TYPE_DESKTOP;
    else if(A_STREQ(buf, "dock"))
        type = WINDOW_TYPE_DOCK;
    else if(A_STREQ(buf, "splash"))
        type = WINDOW_TYPE_SPLASH;
    else if(A_STREQ(buf, "dialog"))
        type = WINDOW_TYPE_DIALOG;
    else if(A_STREQ(buf, "menu"))
        type = WINDOW_TYPE_MENU;
    else if(A_STREQ(buf, "toolbar"))
        type = WINDOW_TYPE_TOOLBAR;
    else if(A_STREQ(buf, "utility"))
        type = WINDOW_TYPE_UTILITY;
    else if(A_STREQ(buf, "dropdown_menu"))
        type = WINDOW_TYPE_DROPDOWN_MENU;
    else if(A_STREQ(buf, "popup_menu"))
        type = WINDOW_TYPE_POPUP_MENU;
    else if(A_STREQ(buf, "tooltip"))
        type = WINDOW_TYPE_TOOLTIP;
    else if(A_STREQ(buf, "notification"))
        type = WINDOW_TYPE_NOTIFICATION;
    else if(A_STREQ(buf, "combo"))
        type = WINDOW_TYPE_COMBO;
    else if(A_STREQ(buf, "dnd"))
        type = WINDOW_TYPE_DND;
    else if(A_STREQ(buf, "normal"))
        type = WINDOW_TYPE_NORMAL;
    else
    {
        warn("Unknown window type '%s'", buf);
        return 0;
    }

    if(w->type != type)
    {
        w->type = type;
        if(w->window != XCB_WINDOW_NONE)
            ewmh_update_window_type(w->window, window_translate_type(w->type));
        luaA_object_emit_signal(globalconf.L, -3, "property::type", 0);
    }

    return 0;
}
示例#19
0
文件: window.c 项目: Asido/AwesomeWM
/** Set the window border color.
 * \param L The Lua VM state.
 * \param window The window object.
 * \return The number of elements pushed on stack.
 */
static int
luaA_window_set_border_color(lua_State *L, window_t *window)
{
    size_t len;
    const char *color_name = luaL_checklstring(L, -1, &len);

    if(color_name &&
       color_init_reply(color_init_unchecked(&window->border_color, color_name, len)))
    {
        xwindow_set_border_color(window_get(window), &window->border_color);
        luaA_object_emit_signal(L, -3, "property::border_color", 0);
    }

    return 0;
}
示例#20
0
文件: window.c 项目: Akulen/awesome
/** Return window struts (reserved space at the edge of the screen).
 * \param L The Lua VM state.
 * \return The number of elements pushed on stack.
 */
static int
luaA_window_struts(lua_State *L)
{
    window_t *window = luaA_checkudata(L, 1, &window_class);

    if(lua_gettop(L) == 2)
    {
        luaA_tostrut(L, 2, &window->strut);
        ewmh_update_strut(window->window, &window->strut);
        luaA_object_emit_signal(L, 1, "property::struts", 0);
        /* We don't know the correct screen, update them all */
        foreach(s, globalconf.screens)
            screen_update_workarea(*s);
    }

    return luaA_pushstrut(L, window->strut);
}
示例#21
0
文件: window.c 项目: Asido/AwesomeWM
/** Set a window border width.
 * \param L The Lua VM state.
 * \param idx The window index.
 * \param width The border width.
 */
void
window_set_border_width(lua_State *L, int idx, int width)
{
    window_t *window = luaA_checkudata(L, idx, &window_class);

    if(width == window->border_width || width < 0)
        return;

    if(window->window)
        xcb_configure_window(globalconf.connection, window_get(window),
                             XCB_CONFIG_WINDOW_BORDER_WIDTH,
                             (uint32_t[]) { width });

    window->border_width = width;

    luaA_object_emit_signal(L, idx, "property::border_width", 0);
}
示例#22
0
文件: window.c 项目: Akulen/awesome
/** Set a window border width.
 * \param L The Lua VM state.
 * \param idx The window index.
 * \param width The border width.
 */
void
window_set_border_width(lua_State *L, int idx, int width)
{
    window_t *window = luaA_checkudata(L, idx, &window_class);
    uint16_t old_width = window->border_width;

    if(width == window->border_width || width < 0)
        return;

    window->border_need_update = true;
    window->border_width = width;

    if(window->border_width_callback)
        (*window->border_width_callback)(window, old_width, width);

    luaA_object_emit_signal(L, idx, "property::border_width", 0);
}
示例#23
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;
    }
}
示例#24
0
文件: window.c 项目: Asido/AwesomeWM
/** Return window struts (reserved space at the edge of the screen).
 * \param L The Lua VM state.
 * \return The number of elements pushed on stack.
 */
static int
luaA_window_struts(lua_State *L)
{
    window_t *window = luaA_checkudata(L, 1, &window_class);

    if(lua_gettop(L) == 2)
    {
        luaA_tostrut(L, 2, &window->strut);
        ewmh_update_strut(window->window, &window->strut);
        luaA_object_emit_signal(L, 1, "property::struts", 0);
        /* FIXME: Only emit if the workarea actually changed
         * (= window is visible, only on the right screen)? */
        foreach(s, globalconf.screens)
            screen_emit_signal(L, s, "property::workarea", 0);
    }

    return luaA_pushstrut(L, window->strut);
}
示例#25
0
/** Remove a tag from screen. Tag must be on a screen and have no clients.
 * \param tag The tag to remove.
 */
void
tag_remove_from_screen(tag_t *tag)
{
    if(!tag->screen)
        return;

    int screen_index = screen_array_indexof(&globalconf.screens, tag->screen);
    int phys_screen = screen_virttophys(screen_index);
    tag_array_t *tags = &tag->screen->tags;

    for(int i = 0; i < tags->len; i++)
        if(tags->tab[i] == tag)
        {
            tag_array_take(tags, i);
            break;
        }

    /* tag was selected? If so, reban */
    if(tag->selected)
        banning_need_update(tag->screen);

    ewmh_update_net_numbers_of_desktop(phys_screen);
    ewmh_update_net_desktop_names(phys_screen);

    /* call hook */
    if(globalconf.hooks.tags != LUA_REFNIL)
    {
        lua_pushnumber(globalconf.L, screen_index + 1);
        luaA_object_push(globalconf.L, tag);
        lua_pushliteral(globalconf.L, "remove");
        luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.tags, 3, 0);
    }

    screen_t *s = tag->screen;
    tag->screen = NULL;

    luaA_object_push(globalconf.L, tag);
    luaA_object_emit_signal(globalconf.L, -1, "property::screen", 0);
    screen_emit_signal(globalconf.L, s, "tag::detach", 1);

    luaA_object_unref(globalconf.L, tag);
}
示例#26
0
/** Append a tag to a screen.
 * \param L The Lua VM state.
 * \param udx The tag index on the stack.
 * \param s The screen.
 */
void
tag_append_to_screen(lua_State *L, int udx, screen_t *s)
{
    tag_t *tag = luaA_checkudata(globalconf.L, udx, &tag_class);

    /* can't attach a tag twice */
    if(tag->screen)
    {
        lua_remove(L, udx);
        return;
    }

    int screen_index = screen_array_indexof(&globalconf.screens, s);
    int phys_screen = screen_virttophys(screen_index);

    tag->screen = s;
    tag_array_append(&s->tags, luaA_object_ref_class(globalconf.L, udx, &tag_class));
    ewmh_update_net_numbers_of_desktop(phys_screen);
    ewmh_update_net_desktop_names(phys_screen);

    luaA_object_push(globalconf.L, tag);
    luaA_object_emit_signal(L, -1, "property::screen", 0);
    lua_pop(L, 1);

    /* call hook */
    if(globalconf.hooks.tags != LUA_REFNIL)
    {
        lua_pushnumber(globalconf.L, screen_index + 1);
        luaA_object_push(globalconf.L, tag);
        lua_pushliteral(globalconf.L, "add");
        luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.tags, 3, 0);
    }

    luaA_object_push(globalconf.L, tag);
    screen_emit_signal(globalconf.L, s, "tag::attach", 1);
}
示例#27
0
/** Emit a button signal.
 * The top of the lua stack has to be the object on which to emit the event.
 * \param L The Lua VM state.
 * \param ev The event to handle.
 */
static void
event_emit_button(lua_State *L, xcb_button_press_event_t *ev)
{
    const char *name;
    switch(XCB_EVENT_RESPONSE_TYPE(ev))
    {
    case XCB_BUTTON_PRESS:
        name = "button::press";
        break;
    case XCB_BUTTON_RELEASE:
        name = "button::release";
        break;
    default:
        fatal("Invalid event type");
    }

    /* Push the event's info */
    lua_pushinteger(L, ev->event_x);
    lua_pushinteger(L, ev->event_y);
    lua_pushinteger(L, ev->detail);
    luaA_pushmodifiers(L, ev->state);
    /* And emit the signal */
    luaA_object_emit_signal(L, -5, name, 4);
}
示例#28
0
int
luaA_object_emit_signal_simple(lua_State *L)
{
    luaA_object_emit_signal(L, 1, luaL_checkstring(L, 2), lua_gettop(L) - 2);
    return 0;
}
示例#29
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);
示例#30
0
/** The property notify event handler handling xproperties.
 * \param ev The event.
 */
static void
property_handle_propertynotify_xproperty(xcb_property_notify_event_t *ev)
{
    xproperty_t *prop;
    xproperty_t lookup = { .atom = ev->atom };
    buffer_t buf;
    void *obj;

    prop = xproperty_array_lookup(&globalconf.xproperties, &lookup);
    if(!prop)
        /* Property is not registered */
        return;

    if (ev->window != globalconf.screen->root)
    {
        obj = client_getbywin(ev->window);
        if(!obj)
            obj = drawin_getbywin(ev->window);
        if(!obj)
            return;
    } else
        obj = NULL;

    /* Get us the name of the property */
    buffer_inita(&buf, a_strlen(prop->name) + a_strlen("xproperty::") + 1);
    buffer_addf(&buf, "xproperty::%s", prop->name);

    /* And emit the right signal */
    if (obj)
    {
        luaA_object_push(globalconf.L, obj);
        luaA_object_emit_signal(globalconf.L, -1, buf.s, 0);
        lua_pop(globalconf.L, 1);
    } else
        signal_object_emit(globalconf.L, &global_signals, buf.s, 0);
    buffer_wipe(&buf);
}

/** The property notify event handler.
 * \param ev The event.
 */
void
property_handle_propertynotify(xcb_property_notify_event_t *ev)
{
    int (*handler)(uint8_t state,
                   xcb_window_t window) = NULL;

    globalconf.timestamp = ev->time;

    property_handle_propertynotify_xproperty(ev);

    /* Find the correct event handler */
#define HANDLE(atom_, cb) \
    if (ev->atom == atom_) \
    { \
        handler = cb; \
    } else
#define END return

    /* Xembed stuff */
    HANDLE(_XEMBED_INFO, property_handle_xembed_info)

    /* ICCCM stuff */
    HANDLE(XCB_ATOM_WM_TRANSIENT_FOR, property_handle_wm_transient_for)
    HANDLE(WM_CLIENT_LEADER, property_handle_wm_client_leader)
    HANDLE(XCB_ATOM_WM_NORMAL_HINTS, property_handle_wm_normal_hints)
    HANDLE(XCB_ATOM_WM_HINTS, property_handle_wm_hints)
    HANDLE(XCB_ATOM_WM_NAME, property_handle_wm_name)
    HANDLE(XCB_ATOM_WM_ICON_NAME, property_handle_wm_icon_name)
    HANDLE(XCB_ATOM_WM_CLASS, property_handle_wm_class)
    HANDLE(WM_PROTOCOLS, property_handle_wm_protocols)
    HANDLE(XCB_ATOM_WM_CLIENT_MACHINE, property_handle_wm_client_machine)
    HANDLE(WM_WINDOW_ROLE, property_handle_wm_window_role)

    /* EWMH stuff */
    HANDLE(_NET_WM_NAME, property_handle_net_wm_name)
    HANDLE(_NET_WM_ICON_NAME, property_handle_net_wm_icon_name)
    HANDLE(_NET_WM_STRUT_PARTIAL, property_handle_net_wm_strut_partial)
    HANDLE(_NET_WM_ICON, property_handle_net_wm_icon)
    HANDLE(_NET_WM_PID, property_handle_net_wm_pid)
    HANDLE(_NET_WM_WINDOW_OPACITY, property_handle_net_wm_opacity)

    /* background change */
    HANDLE(_XROOTPMAP_ID, property_handle_xrootpmap_id)

    /* If nothing was found, return */
    END;

#undef HANDLE
#undef END

    (*handler)(ev->state, ev->window);
}